theme: fancy
highlight: a11y-light
简单数据类型的代理
简单数据类型需要使用ref,实际上ref的背后还是reactive.本质是手动给他加一层,并且给他一个ref的标记__v_isRef
function ref(val) {
const wrapper = {
value: val,
};
// 使用 Object.defineProperty 在 wrapper 对象上定义一个不可枚举的属性 __v_isRef,并且值为 true
Object.defineProperty(wrapper, "__v_isRef", {
value: true,
});
return reactive(wrapper);
}
let proxyNum = ref(1);
effect(() => {
console.log(proxyNum.value);
});
proxyNum.value++;
setup暴露出的响应式对象,经过...会失去响应式,首先来模拟一下这种情景
let newObj = {
...proxyData }
effect(() => {
console.log(newObj.age)
});
newObj.age++
问题关键在于有没有办法能够帮助我们实现:在副作用函数内,即使通过普通对象 newObj 来访问属性值,也能够建立响应联系,方法是有的,可以借助访问器,同时要有get和set.如果没有set不能修改数据
newObj = {
age: {
get value() {
return proxyData.age;
},
set value(val) {
proxyData["age"] = val;
},
},
};
effect(() => {
console.log(newObj.age.value);
});
newObj.age.value++;
可以将上面的逻辑封装成一个函数,并添加__v_isRef
function toRef(proxyData, key) {
let wrapper = {
get value() {
return proxyData[key];
},
set value(val) {
proxyData[key] = val;
},
};
Object.defineProperty(wrapper, "__v_isRef", {
value: true,
});
return wrapper;
}
也可以一次性完成对象的操作,这样newObj修改他的值也会有触发响应
function toRefs(obj) {
const ret = {
};
for (const key in obj) {
ret[key] = toRef(obj, key);
}
return ret;
}
const newObj = {
...toRefs(obj) }
我们都知道ref类型在模板是不需要使用.value的,这其实要借助我们之前的标__v_isRef,在get中判断是否是ref返回不同的数据
return value.__v_isRef ? value.value : value
至此响应系统的内容结束