简述 Vue 2.0 响应式数据的原理( 重点 )?

参考回答

Vue 2.0 的响应式数据系统是基于 Object.defineProperty 实现的,通过对数据对象的属性进行“getter”和“setter”操作,监听数据的变化,并在数据变化时更新视图。其原理可以分为以下几个关键点:

  1. 数据劫持(Data Hijacking)
    Vue 通过 Object.defineProperty 对数据对象的每个属性进行劫持,在属性访问(getter)和修改(setter)时触发相应的逻辑。

  2. 依赖收集(Dependency Collection)
    当组件访问某个响应式数据时,Vue 会在该数据的 getter 中收集当前组件作为依赖(称为 “watcher”),在数据变化时,Vue 会通知这些依赖进行更新。

  3. 视图更新(View Update)
    数据发生变化时,通过 setter 被触发,通知所有依赖的组件更新视图。

详细讲解与拓展

1. 数据劫持(Data Hijacking)

Vue 通过 Object.defineProperty 对数据对象的属性进行“劫持”,即在数据读取和修改时添加 gettersetter,来实现数据的观察与控制。

例如,假设我们有以下数据对象:

let data = {
  message: 'Hello Vue!'
}

Vue 会在内部将这个对象的 message 属性劫持,添加 gettersetter,代码大致如下:

Object.defineProperty(data, 'message', {
  get() {
    // 当访问 message 时执行
    console.log('Getter called');
    return this._message;
  },
  set(newValue) {
    // 当修改 message 时执行
    console.log('Setter called');
    this._message = newValue;
    // 通知视图更新
    this.updateView();
  }
});

当我们访问或修改 message 时,Vue 会执行 gettersetter 中的逻辑。

2. 依赖收集(Dependency Collection)

当 Vue 组件访问响应式数据时(例如,this.message),Vue 会将当前组件(通常是 watcher 对象)作为依赖,记录下来。watcher 是一个用来记录数据变化的对象,它会在数据发生变化时重新渲染组件。

假设组件中有如下代码:

<p>{{ message }}</p>

在渲染时,message 会触发 getter,在 getter 内部,Vue 会收集当前组件作为依赖,并将其存储在 message 的依赖队列中。

3. 视图更新(View Update)

当数据发生变化时,setter 会被触发,setter 内部会通知所有依赖的 watcher,然后 watcher 会重新执行组件的渲染函数,更新视图。

例如,如果我们修改了 message 的值:

data.message = 'Hello World!';

setter 会被调用,视图会自动更新,重新渲染对应的组件。

4. 数组和对象的响应式

Vue 对数组和对象的响应式处理也采用类似的原理,但有一些额外的处理来确保数组的变化(如添加、删除元素)和对象的嵌套属性也能被正确监听。

  • 数组:Vue 通过重写数组的变更方法(如 pushpopshiftunshiftsplice 等)来触发视图更新。
  • 对象:Vue 会递归地对对象中的每个属性进行响应式处理,确保嵌套属性的变化也能触发视图更新。

总结

Vue 2.0 的响应式原理通过 Object.defineProperty 对对象的每个属性进行劫持,在数据的读取和修改时执行 gettersetter,收集依赖并在数据变化时更新视图。这种机制使得 Vue 可以在数据变化时自动更新视图,实现了高效的数据绑定和视图更新。

发表评论

后才能评论