Vue3.0接入踩坑记录
程序员文章站
2022-06-11 19:04:13
...
Vue3.0 响应式原理
// 通过Proxy代理数据,实现对数据所有属性的set,get监听以实现数据绑定,并返回一个包装对象
const data = {
name: "bob",
age: 18,
};
// 被代理的data元素只能为object
const proxyData = new Proxy(data, {
get: function (target, prop) {
return target[prop];
},
set: function (target, prop, value) {
target[prop] = value;
},
});
// proxyData 为包装对象
console.log(proxyData);
ref()
与reactive()
用法上的区别
两个方法都是用于为数据添加响应式绑定,ref()
一般用于给基础数据添加绑定 字符串/数字绑定后使用.value
访问。reactive()
一般用于给 object 等复杂类型添加动态绑定,绑定后直接访问即可。
const a = ref({ name: 'bob', age: 18 });
const b = reactive({ name: 'bob', age: 18 });
console.log('a::', a, 'b::', b);
通过以上代码可以发现,ref()
在绑定后返回了一个包装对象RefImpl,而包装对象的value属性才指向了proxy代理的观测数据,所以需要用.value访问,而通过reactive()
包装的对象则没有这个副作用,如果直接通过reactive
包装简单数据,数据将不会被监听。
原因:基于Proxy监听数据,只能监听对象。所以ref(null)
在绑定时会将其包装成为{ value:null }
再进行监听。
为什么解构赋值要用toRefs()
包裹
在js中使用解构赋值时,虽然赋值方式为浅拷贝,但却无法触发Proxy包装对象的set方法,如果直接解构则会破坏对应的响应性,所以需要用toRefs重新绑定。
// 源码
function toRefs(object) {
if ((process.env.NODE_ENV !== 'production') && !isProxy(object)) {
console.warn(`toRefs() expects a reactive object but received a plain one.`);
}
const ret = isArray(object) ? new Array(object.length) : {}; // 判断传入类型
for (const key in object) { // 将每个属性都转换为响应对象Ref
ret[key] = toRef(object, key);
}
return ret;
}
function toRef(object, key) {
return isRef(object[key])
? object[key]
: new ObjectRefImpl(object, key);
}