vue3源码之isReadonly && isReactive

88 阅读1分钟

isReadonly: 检测数据是否是只读 isReactive: 检测数据是否是响应式数据
单元测试:

  describe('readonly', ()=> {
    it('should make nested value readonly, () => {
      const original = { foo: 1, bar: { baz: 2}};
      const wrapped = readonly(original);
      expect(wrapped).not.toBe(original);
      expect(isReadonly(wrapped)).toBe(true);
      expect(isReactive(original)).toBe(false);
      expect(wrapped.foo).toBe(1);
    }
  })

js实现:

  export const enum ReactiveFlags{
    IS_REACTIVE = '_v_isReactive',
    IS_READONLY = '_v_isReadonly'
  }
  export function isReactive(value){
    // 两个!!用于将数据进行类型转换如果数据非reactive,此时返回undefined,进行类型转换,  转换为boolean
    return !!value[ReactiveFlags.IS_REACTIVE]
  }
  export function isReadonly(value){
    return !!value[ReactiveFlags.IS_READONLY]
  }
  export function Reactive(raw){
    return new Proxy(raw, {
      get: createGetter(),
      set: createSetter(),
    }
  }
  function createGetter(isRadonly = false){
    return function get(target, key){
      if(key === ReactiveFlags.IS_REACTIVE){
        return !isReadonly;
      }
      if(key === ReactiveFlags.IS_READONLY){
        return isReadOnly;
      }
      const res = Reflect.get(target, key);
      if(!isReadonly){
        track(target, key);
      }
      return res;
    }
  }
  function createSetter(){
    return function set(target, key, value){
      const res = Reflect.set(target, key, value);
      trigger();
      return res;
    }
  }