根据单侧实现功能
ref.spec.ts
/** 看得见的思考
* 1. get,获取的时候主要考虑是ref对象还是普通对象,可以借助unRef
* 2. set,更新要考虑是普通对象还是ref,要保持响应
* 2.1 如果普通对象,则更新.value的值
* 2.2 如果是ref,则直接替换即可
*/
it("proxyRefs", () => {
const user = {
age: ref(10),
name: "xiaohong",
};
const proxyUser = proxyRefs(user);
expect(user.age.value).toBe(10);
expect(proxyUser.age).toBe(10);
expect(proxyUser.name).toBe("xiaohong");
(proxyUser as any).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);
});
实现
/*
* @Author: Lin zefan
* @Date: 2022-03-17 18:23:36
* @LastEditTime: 2022-03-21 23:28:20
* @LastEditors: Lin zefan
* @Description: ref
* @FilePath: \mini-vue3\src\reactivity\ref.ts
*
*/
export function isRef(ref) {
return !!ref.__v_isRef;
}
export function unRef(ref) {
return isRef(ref) ? ref.value : ref;
}
export function proxyRefs(ref) {
return new Proxy(ref, {
get(target, key) {
// 需要判断target是ref对象还是其他,ref帮忙提取.value
return unRef(Reflect.get(target, key));
},
set(target, key, value) {
/** 思考
* 1. 新老值对比,如果老值是ref,新值不是,那应该是更新老值的.value
* 2. 如果新值是ref,直接替换即可
*/
if (isRef(target[key]) && !isRef(value)) {
target[key].value = value;
return target;
} else {
return Reflect.set(target, key, value);
}
},
});
}