11-实现 proxyRefs

349 阅读1分钟

根据单侧实现功能

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);
      }
    },
  });
}