Vue2、3的响应式原理对比

118 阅读1分钟

Vue3 的响应式数据实现原理,使用Proxy替换Object.defineProperty;新增Composition API,更好的逻辑复用和代码组织

Vue2的响应式

  • 实现原理:

    • 对象类型:通过 Object.defineProperty() 对属性的读取、修改进行拦截(数据劫持)。
    • 数组类型:通过重写更新数组的一系列方法来实现拦截。(对数组的变更方法进行了包裹)。
  • 存在问题:

    • 新增属性、删除属性, 界面不会更新。
    • 直接通过下标修改数组, 界面不会自动更新。
  • 实现如下:

<script type="text/javascript">
  // 源数据
  let person = {
    age: 12,
    name: 悟空
  }
  /*
    模拟Vue2的响应原理
  */
  let p = {}
  Object.defineProperty(p, 'name', {
    // configurable为true,就可以删除属性了
    // configurable: true,
    get() {
      console.log('有人读取了name属性')
      return person.name
    },
    set(value) {
      console.log('有人修改了name属性')
      person.name = value
    }
  })
  Object.defineProperty(p, 'age', {
    get() {
      console.log('有人读取了age属性')
      return person.age
    },
    set(value) {
      console.log('有人修改了age属性')
      person.age = value
    }
  })
</script>

Vue3的响应式

  • 实现原理:
    • 通过 Proxy(代理): 是window的构建函数,拦截对象中任意属性的变化, 包括:属性值的读写、属性的添加、属性的删除等。
    • 通过 Reflect(反射): 对源对象的属性进行操作。
  • 实现如下:
<script type="text/javascript">
  let person = {
    age: 12,
    name: 'bajie'
  }
  const p = new Proxy(person, {
    // 读取属性
    get(target, propName) {
      console.log('读取了属性')
      return Reflect.get(target, propName)
    },
    // 修改属性
    set(target, propName, value) {
      console.log('修改、增加了属性')
      Reflect.set(target, propName, value)
    },
    // 删除属性
    deleteProperty(target, propName) {
      console.log('删除了属性')
      Reflect.deleteProperty(target, propName)
    }
  })
<script type="text/javascript">