返回

数据响应式原理 — Watcher 类与依赖收集

前端

导言

在上一篇文章中,我们探讨了 Vue.js 中数组响应式处理的机制,学习了如何使用 ES6 Proxy 来监听数组的变化并触发视图更新。本篇将继续我们的探索之旅,深入了解 Vue.js 数据响应式的核心机制——Watcher 类和依赖收集。

Watcher 类

Watcher 是 Vue.js 中一个强大的类,负责监视数据变化并触发相应的更新。每个 Watcher 实例都与一个特定属性相关联,当该属性的值发生变化时,Watcher 就会被触发。

创建 Watcher

Watcher 实例是在组件实例化过程中创建的,如下所示:

const watcher = new Watcher(vm, exprOrFn, cb, options);

其中,

  • vm:组件实例
  • exprOrFn:要监视的数据属性或计算属性的表达式或函数
  • cb:当属性值发生变化时要调用的回调函数
  • options:可选配置,例如 lazy、deep、immediate 等

依赖收集

为了实现响应性,Vue.js 需要知道哪些属性会被 Watcher 使用,以便在这些属性值发生变化时触发 Watcher。这个过程称为依赖收集。

当创建一个 Watcher 时,Vue.js 会自动收集 Watcher 所依赖的属性,并将其保存在 Watcher 实例的 deps 数组中。这个过程是在 Watcher 的 get() 方法中进行的:

Watcher.prototype.get = function get() {
  this.beforeGet();
  let value;
  try {
    value = this.getter.call(this.vm, this.vm);
  } catch (e) {
    if (this.user) {
      // 如果是用户 Watcher,则抛出错误
      warn(`Failed to evaluate user watcher getter: ${this.getter}`, e);
    } else {
      // 否则,将错误信息存储在 Watcher 实例上
      this.error = e;
    }
  } finally {
    this.afterGet();
  }
  return value;
};

get() 方法中,会调用 getter 函数来获取属性值。在获取值之前和之后,都会调用 beforeGet()afterGet() 方法,这两个方法负责收集依赖和清理依赖。

依赖更新

当属性值发生变化时,Vue.js 会通知所有依赖于该属性的 Watcher。Watcher 将自身添加到属性的依赖者列表中,从而建立了一种双向联系。当属性值发生变化时,属性会通知它的依赖者,依赖者就会触发更新。

应用更新

当 Watcher 被触发时,它将调用其回调函数。回调函数负责更新视图或执行其他必要的更新操作。

总结

Watcher 类和依赖收集是 Vue.js 数据响应式系统的重要组成部分。通过创建 Watcher 并收集依赖,Vue.js 能够有效地监视数据变化并触发相应的更新,从而实现高效的数据响应性。了解这些机制对于深入理解 Vue.js 底层原理至关重要。