返回

Vue面试真题:从源码解析响应式原理(28)

前端

引言

作为 Vue.js 的核心机制,响应式系统使数据和视图紧密相连,从而实现数据变化的自动更新。本文将通过源码解析,揭秘 Vue.js 响应式系统的幕后奥秘。

Object.defineProperty

Vue.js 使用 Object.defineProperty() 方法在对象属性上定义 getter 和 setter,实现数据的响应式跟踪。当属性被读取时,getter 被调用,此时 Vue.js 可以监测到属性的读取操作,并收集依赖关系。当属性被修改时,setter 被调用,Vue.js 将触发更新操作,使视图与新数据保持同步。

Object.defineProperty(obj, 'name', {
  get() {
    // 触发 getter,收集依赖
    return this._name;
  },
  set(newName) {
    // 触发 setter,修改数据并触发更新
    this._name = newName;
    updateView();
  }
});

Proxy

在 Vue 3.0 及以上版本中,Vue.js 引入了 Proxy 对象,进一步增强了响应式系统的效率。Proxy 允许拦截对象属性的操作,无需再逐个定义 getter 和 setter。

const obj = new Proxy({ name: 'John' }, {
  get(target, prop) {
    // 拦截属性读取,收集依赖
    return target[prop];
  },
  set(target, prop, value) {
    // 拦截属性修改,修改数据并触发更新
    target[prop] = value;
    updateView();
  }
});

依赖收集

依赖收集是 Vue.js 响应式系统的重要组成部分。当属性读取时,Vue.js 会将当前组件实例添加到属性的依赖数组中。当属性修改时,Vue.js 会遍历依赖数组,触发对应组件的更新操作。

响应式系统实现原理

  1. 定义响应式属性: 使用 Object.defineProperty 或 Proxy 定义对象属性,并为其配置 getter 和 setter。
  2. 依赖收集: 当属性读取时,将当前组件实例添加到属性的依赖数组中。
  3. 属性修改: 当属性修改时,触发 setter,修改数据并调用 updateView() 方法。
  4. 更新视图: updateView() 方法触发组件更新,使视图与新数据保持一致。

总结

Vue.js 响应式系统通过 Object.defineProperty 或 Proxy 实现属性的 getter 和 setter 拦截,并利用依赖收集机制,高效且准确地响应数据变化。理解这些底层原理,有助于深入掌握 Vue.js 响应式系统的精髓。