14_实现proxyRefs功能
🙋 Hello,I'm IamZJT!
✍️ 一名菜鸟前端开发工程师!📦 Github项目地址:zjt-mini-vue3。
🖐️ 欢迎点赞➕star,期盼与您并肩前行...
(一)单元测试
// src/reactivity/tests/ref.spec.ts
it('proxyRefs', () => {
const user = {
age: ref(10),
name: 'iamzjt'
};
const proxyUser = proxyRefs(user);
expect(user.age.value).toBe(10);
expect(proxyUser.age).toBe(10);
expect(proxyUser.name).toBe('iamzjt');
// proxyUser.age = 20;
// expect(proxyUser.age).toBe(20);
// expect(user.age.value).toBe(20);
// proxyUser.age = ref(10);
// expect(proxyUser.age).toBe(10);
// expect(user.age.value).toBe(10);
});
先看上面没有被注释的部分,可以看到proxyRefs会处理响应式对象并返回一个新对象,而这个新对象访问原先的ref
变量时,就不用写.value了。
这是不是就跟template中写变量一样。
(二)代码实现
分析一下可以看出,实际上就是获取属性值的时候,判断一下是否是ref,是的话返回.value
,不是的话,就返回本身。转头一想,这不就是之前实现的unRef
吗?现在只要拦截get操作即可。
// src/reactivity/ref.ts
export function proxyRefs(objectWithRefs) {
// * get: age (ref) -> return .value
// * get: not ref -> return value
return new Proxy(objectWithRefs, {
get(target, key) {
return unRef(Reflect.get(target, key));
}
});
}
那接下来我们放开下面两段单测,来看一下。
proxyUser.age = 20;
expect(proxyUser.age).toBe(20);
expect(user.age.value).toBe(20);
proxyUser.age = ref(10);
expect(proxyUser.age).toBe(10);
expect(user.age.value).toBe(10);
当proxyUser.age发生变化后,可以看到处理后的对象的age值和原来的user的age
也发生了变化。即:一次性改了两个值,这意味着我们要拦截set操作。
并且,不论新设置的值是不是ref,都能一起改变两个值。
那接下来就来实现一下。
// * set ref -> .value
set(target, key, value)
{
if (isRef(target[key]) && !isRef(value)) {
return target[key].value = value;
} else {
return Reflect.set(target, key, value);
}
}
ps
🎯 如果您看到这里,请不要走开。
🎉 这是一个早起俱乐部:三更灯火五更鸡!
⭐️ 寻找 志同道合 的小伙伴,我们一起 早起。