深入 Vue 的一些实现原理

2023-03-22· 8min

#响应式

#实现方式:Proxy + Reflect

#Proxy

  • Proxy
    对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义
  • 优点:
    • 直接监听对象而非属性
    • 可以监听数组变化
    • 返回并操作的是个新对象
  • 缺点:
    • 浏览器兼容性问题,且无法用
      polyfill
      磨平

#Reflect

  • 使用
    Reflect
    Proxy
    内部调用对象的默认行为
  • 优势
    • Reflect
      对象拥有
      Proxy
      对象具有的代理方法,并以静态方法的形式存在
    • 使对象操作更加合理,如定义不存在属性时不会报错而是返回
      false
    • 使对象操作都变成函数行为

#简单实现

function reactive(obj) {
  if (typeof obj !== "object" && obj !== null) {
    return obj;
  }
  const p1 = new Proxy(obj, {
    get(target, key, receiver) {
      const res = Reflect.get(target, key, receiver);
      console.log(`get[${key}]`, res);
      return typeof res === "object" ? reactive(res) : res;
    },
    set(target, key, value, receiver) {
      const res = Reflect.set(target, key, value, receiver);
      console.log(`set[${key}]`, value);
      return res;
    },
    deleteProperty(target, key) {
      const res = Reflect.deleteProperty(target, key);
      console.log(`delp${key}]`, res);
      return res;
    },
  });
  return p1;
}

var r1 = reactive({
  kk: { k: 1 },
});

console.log(`${r1.kk.k}\n\n`); // 1
r1.kk.k = 2;
console.log(`\n`);
console.log(`${r1.kk.k}`); // 2

#参考文献


#实现方式:Object.defineProperty()

#Object.defineProperty()

  • Object.defineProperty()
    静态方法会直接在一个对象上定义一个新属性,或修改其现有属性,并返回此对象
  • 优点:
    • 兼容性好,支持 IE9
  • 缺点:
    • 无法监听数组的变化
    • 无法监听对象动态新增的属性

#简单实现

function defineReactive(obj, key, val) {
  Object.defineProperty(obj, key, {
    get() {
      console.log(`get[${key}]: ${val}`);
      return val;
    },
    set(newVal) {
      if (newVal !== val) {
        console.log(`set[${key}]: val[${val}] newVal[${newVal}]`);
        val = newVal;
      }
    },
  });
}

var o2 = { k: 1 };
defineReactive(o2, "k", o2.k);

setTimeout(() => {
  o2.k = "3";
}, 2000);

#参考文献