Skip to main content

Vue 双向数据绑定原理(2/3)

  • vue2 的原理

Object.defineProperty()

// 劫持了一层   const data = {      name: "zhang",      age: 20    }    observer(data)    function observer(target) {      if (typeof target !== "object" || target === null) {        return target      }      for (let key in target) {        defineReactive(target, key, target[key])      }    }    function defineReactive(target, key, obj) {      Object.defineProperty(target, key, {        get() {          return value        },        set(newval) {          value = newval;          console.log("更新");        }      })    }    data.age = 10
// 对象 const data = {      name: "zhang",      age: 20    }    observer(data)    function observer(target) {      if (typeof target !== "object" || target === null) {        return target      }      for (let key in target) {        defineReactive(target, key, target[key])      }    }    function defineReactive(target, key, value) {      // 劫持深层次的值 属性值为对象的情况      observer(value)      // 添加上一行代码      Object.defineProperty(target, key, {        get() {          return value        },        set(newval) {          value = newval;          console.log("更新");        }      })    }    data.age = 10
 const data = {      name: "zhang",      age: 20    }    observer(data)    function observer(target) {      if (typeof target !== "object" || target === null) {        return target      }      for (let key in target) {        defineReactive(target, key, target[key])      }    }    function defineReactive(target, key, value) {      // 劫持深层次的值 属性值为对象的情况      observer(value)      // 添加上一行代码      Object.defineProperty(target, key, {        get() {          return value        },        set(newval) {          observer(newval)          value = newval;          console.log("更新");        }      })    }    // 删除时不响应    delete data.age    //  添加时不响应    data.test = "someing"
  • push pop 等方法不能响应式
  const data = {      name: "zhang",      age: 20,      color: ["blue", "red"]    }    // 获取 原生array 对象的push等方法    const oldArrayProto = Array.prototype;    const newArrayProto = Object.create(oldArrayProto);
    ['push', 'pop', 'shift', 'unshift', 'splice'].forEach(methodName => {      newArrayProto[methodName] = function () {        console.log("更新");        oldArrayProto[methodName].call(this, ...arguments);      }    })    observer(data)    function observer(target) {      if (typeof target !== "object" || target === null) {        return target;      }      // 添加判断      if (Array.isArray(target)) {        target.__proto__ = newArrayProto;      }      for (let key in target) {        defineReactive(target, key, target[key]);      }    }    function defineReactive(target, key, value) {      // 劫持深层次的值 属性值为对象的情况      observer(value);      // 添加上一行代码      Object.defineProperty(target, key, {        get() {          return value;        },        set(newval) {          observer(newval);          value = newval;          console.log("更新");        }      })    }    data.color.push("green")

区别#

  • Object.defineProperty()

    • 是劫持对象的属性,对象属性的添加和删除,没有响应
    • 兼容低版本浏览器
    • 操作数组不响应
  • Proxy

    • 是代理的整个对象,对对象属性的添加和删除都有响应
    • 不兼容低版本浏览器