目标

实现浅层的 Readonly

  1. import { isReadonly, shallowReadonly } from '../reactive';
  2. describe('shallowReadonly', () => {
  3. it('should not make non-reactive properties reactive', () => {
  4. const props = shallowReadonly({ n: { foo: 1 } });
  5. expect(isReadonly(props)).toBe(true); // 只有表层为响应性对象
  6. expect(isReadonly(props.n)).toBe(false);
  7. });
  8. it('warn where call set', () => {
  9. console.warn = jest.fn();
  10. const user = shallowReadonly({ age: 10 });
  11. user.age = 11;
  12. expect(console.warn).toBeCalled();
  13. });
  14. });

实现

实际就是阻止做上一节的嵌套 readonly

  1. const shallowReadonlyGet = createGetter(true, true);
  2. // 增加 shallow 做标记
  3. function createGetter(isReadonly = false, shallow = false) {
  4. return function get(target, key) {
  5. if (key === ReactiveFlags.IS_REACTIVE) {
  6. return !isReadonly;
  7. } else if (key === ReactiveFlags.IS_READONLY) {
  8. return isReadonly;
  9. }
  10. const res = Reflect.get(target, key);
  11. // 如果是 shallow 直接返回 res
  12. if (shallow) {
  13. return res;
  14. }
  15. if (isObject(res)) {
  16. return isReadonly ? readonly(res) : reactive(res);
  17. }
  18. if (!isReadonly) {
  19. track(target, key);
  20. }
  21. return res;
  22. };
  23. }
  24. // 实现专为 shallowReadonly 的 getter
  25. // 先用 readonlyHandlers,再覆写 get 为 shallowReadonlyGet
  26. // 这样会保留 readonly set 抛出警告
  27. export const shallowReadonlyHandlers = extend({}, readonlyHandlers, {
  28. get: shallowReadonlyGet,
  29. });
  1. export function shallowReadonly(raw) {
  2. return createActiveObject(raw, shallowReadonlyHandlers);
  3. }