返回

Vue响应式原理学习(三)— Watcher的实现

前端







众所周知,Vue是在触发数据的get时,收集依赖,改变数据时触发set,达到派发更新的目的。依赖收集和派发更新的代码在上一篇文章,有简单解释过。我们再来重温下代码:

```js
//依赖收集
const target = get(obj, key)
if (target && typeof target === 'object') {
  activeEffect(target)
}

//派发更新
if (computed && typeof computed === 'function') {
  const context = this._computedWatchers[name]
  activeEffect(context)
  const res = computed.call(context, this)
  activeEffect(dep)
  return res
}
这里我省略了部分用于判断和兼容的代码,因为感觉一下子要看所有代码的话,会有些懵比。我们现在知道了,Vue是如何实现响应式的了,那么,下面我们就来看看,Watcher是如何实现的。

Watcher的实现原理其实很简单,就是通过一个类来封装对数据的收集和更新。我们先来看一下Watcher的构造函数:

```js
class Watcher {
  constructor(vm, exprOrFn, options, cb) {
    this.vm = vm
    this.getter = exprOrFn
    this.cb = cb
    this.options = options
    this.dirty = this.lazy // 是否是惰性Watcher
    this.deps = [] // 用来存放Watcher依赖的Dep实例
    this.newDeps = [] // 用来存放新生成的Dep实例
    this.depIds = new Set() // 用来存放Watcher依赖的Dep实例的id
    this.newDepIds = new Set() // 用来存放新生成的Dep实例的id
    this.getValue() // 初始化时就将依赖收集起来
  }
}
可以看到,Watcher的构造函数接收了四个参数:

* vm:当前的Vue实例
* exprOrFn:要监听的数据表达式或函数
* options:一些配置选项,比如lazy、immediate等
* cb:回调函数,在数据变化时触发

Watcher的实现原理很简单,就是通过一个类来封装对数据的收集和更新。我们先来看一下Watcher的构造函数:

```js
class Watcher {
  constructor(vm, exprOrFn, options, cb) {
    this.vm = vm
    this.getter = exprOrFn
    this.cb = cb
    this.options = options
    this.dirty = this.lazy // 是否是惰性Watcher
    this.deps = [] // 用来存放Watcher依赖的Dep实例
    this.newDeps = [] // 用来存放新生成的Dep实例
    this.depIds = new Set() // 用来存放Watcher依赖的Dep实例的id
    this.newDepIds = new Set() // 用来存放新生成的Dep实例的id
    this.getValue() // 初始化时就将依赖收集起来
  }
}
可以看到,Watcher的构造函数接收了四个参数:

* vm:当前的Vue实例
* exprOrFn:要监听的数据表达式或函数
* options:一些配置选项,比如lazy、immediate等
* cb:回调函数,在数据变化时触发

Watcher的实现原理很简单,就是通过一个类来封装对数据的收集和更新。我们先来看一下Watcher的构造函数:

```js
class Watcher {
  constructor(vm, exprOrFn, options, cb) {
    this.vm = vm
    this.getter = exprOrFn
    this.cb = cb
    this.options = options
    this.dirty = this.lazy // 是否是惰性Watcher
    this.deps = [] // 用来存放Watcher依赖的Dep实例
    this.newDeps = [] // 用来存放新生成的Dep实例
    this.depIds = new Set() // 用来存放Watcher依赖的Dep实例的id
    this.newDepIds = new Set() // 用来存放新生成的Dep实例的id
    this.getValue() // 初始化时就将依赖收集起来
  }
}