返回

Vue3.0源码逐行解析(三):响应系统

前端

Vue3.0源码逐行解析(三):响应系统

Vue2 和 Vue3 的响应式系统概念从框架本身来看没有任何改变。我们来回顾下 Vue2 说:

  • 数据变化时通知视图更新

  • 通过 Object.defineProperty实现

Vue3说:

  • 数据变化时通知视图更新

  • 通过 Proxy实现

虽然概念相似,但底层实现方式却有本质的不同。Vue2 采用的是 ES5 Object.defineProperty,而 Vue3 则采用了 ES6 Proxy。

Vue2 的响应式系统

Vue2 中,通过 Object.defineProperty 来劫持对象的属性,当属性值发生改变时,触发 setter 方法,从而实现响应式更新。这种方式虽然简单易懂,但是在某些情况下存在一定的局限性,例如:

  • 无法劫持数组的变化

  • 无法劫持对象的新增属性

  • 无法劫持对象属性的删除

Vue3 的响应式系统

Vue3 中,通过 Proxy 来劫持整个对象,当对象内部发生任何变化时,都会触发 Proxy 的相关方法,从而实现响应式更新。这种方式不仅解决了 Vue2 中存在的局限性,而且还带来了以下优势:

  • 可以劫持数组的变化

  • 可以劫持对象的新增属性

  • 可以劫持对象属性的删除

  • 性能更好

Vue3 中如何使用 Proxy 实现响应式数据

在 Vue3 中,通过 createReactive 函数来创建响应式数据。该函数内部使用 Proxy 来劫持对象,并返回一个响应式代理对象。

function createReactive(target) {
  return new Proxy(target, {
    get(target, key, receiver) {
      // ...
    },
    set(target, key, value, receiver) {
      // ...
    },
    // ...
  });
}

当我们使用响应式代理对象时,对其进行任何操作,都会触发 Proxy 的相关方法,从而实现响应式更新。

举个例子

const obj = createReactive({
  name: '张三',
  age: 18
});

obj.name = '李四';

console.log(obj.name); // '李四'

在上面的例子中,当我们修改 obj.name 的值时,触发了 Proxy 的 set 方法,从而实现了响应式更新。

Vue3 的响应式系统相比于 Vue2 有哪些优势

  • 性能更好:Proxy 的性能要优于 Object.defineProperty。

  • 更全面:Proxy 可以劫持数组的变化、对象的新增属性、对象属性的删除等,而 Object.defineProperty 无法做到这一点。

  • 更灵活:Proxy 可以通过不同的配置来实现不同的响应式行为,而 Object.defineProperty 则相对比较死板。