目标
实现浅层的 Readonly
import { isReadonly, shallowReadonly } from '../reactive';
describe('shallowReadonly', () => {
it('should not make non-reactive properties reactive', () => {
const props = shallowReadonly({ n: { foo: 1 } });
expect(isReadonly(props)).toBe(true); // 只有表层为响应性对象
expect(isReadonly(props.n)).toBe(false);
});
it('warn where call set', () => {
console.warn = jest.fn();
const user = shallowReadonly({ age: 10 });
user.age = 11;
expect(console.warn).toBeCalled();
});
});
实现
实际就是阻止做上一节的嵌套 readonly
const shallowReadonlyGet = createGetter(true, true);
// 增加 shallow 做标记
function createGetter(isReadonly = false, shallow = false) {
return function get(target, key) {
if (key === ReactiveFlags.IS_REACTIVE) {
return !isReadonly;
} else if (key === ReactiveFlags.IS_READONLY) {
return isReadonly;
}
const res = Reflect.get(target, key);
// 如果是 shallow 直接返回 res
if (shallow) {
return res;
}
if (isObject(res)) {
return isReadonly ? readonly(res) : reactive(res);
}
if (!isReadonly) {
track(target, key);
}
return res;
};
}
// 实现专为 shallowReadonly 的 getter
// 先用 readonlyHandlers,再覆写 get 为 shallowReadonlyGet
// 这样会保留 readonly set 抛出警告
export const shallowReadonlyHandlers = extend({}, readonlyHandlers, {
get: shallowReadonlyGet,
});
export function shallowReadonly(raw) {
return createActiveObject(raw, shallowReadonlyHandlers);
}