isReactive
单元测试
// reactive.spec.ts
describe("reactive", () => {
it("happy path", () => {
const original = { foo: 1 };
const observed = reactive(original);
expect(isReactive(observed)).toBe(true);
expect(isReactive(original)).toBe(false);
});
});
分析:
- 创建一个 reactive 其实就是返回代理对象
- 那么怎么知道代理对象是不是 reactive
- 通过 get 操作的 isReadonly 变量可以知道当前对象是什么类型
// baseHandlers.ts
function createGetter(isReadonly = false) {
return function get(target, key) {
...
};
}
目标:当调用 isReactive 时触发 get
实现代码
// baseHandlers.ts
function createGetter(isReadonly = false) {
return function get(target, key) {
const res = Reflect.get(target, key);
if (key === ReactiveFlags.IS_REACTIVE) {
return !isReadonly;
}
...
};
}
// reactive.ts
export const enum RactiveFlags {
IS_REACTIVE = "__v_isReactive",
IS_READONLY = "__v_isReadonly",
}
export function isReactive(value) {
return !!value[ReactiveFlags.IS_REACTIVE];
}
如果 value 值不是一个 proxy, 那么不会调用 baseHandler 里的 get 方法,然后本身身上没有挂载这个key,所以得到的值会是一个 undefined, 所以这里返回值要转换成布尔值、
isReadonly
单元测试
// readonly.spce.ts
describe("readonly", () => {
it("happy path", () => {
const original = { foo: 1, bar: { baz: 2 } };
const wrapped = readonly(original);
expect(isReadonly(wrapped)).toBe(true);
expect(isReadonly(original)).toBe(false);
});
});
思路和 isReactive 一样,直接上实现代码
实现代码
// baseHandlers.ts
function createGetter(isReadonly = false) {
return function get(target, key) {
const res = Reflect.get(target, key);
if (key === ReactiveFlags.IS_REACTIVE) {
return !isReadonly;
} else if (key === ReactiveFlags.IS_READONLY) {
return isReadonly;
}
...
};
}
// reactive.ts
export const enum ReactiveFlags {
IS_REACTIVE = "__v_isReactive",
IS_READONLY = "__v_isReadonly",
}
export function isReadonly(value) {
return !!value[ReactiveFlags.IS_READONLY];
}