【vueJs源码】阅读之vm.$watch函数_数据

我们经常使用watch肯定知道它,他和computer一样都是数据发生变化都会触发它。今天我们就来了解一下它的原理。

他的用法

Vue.prototype.$watch = function (
    expOrFn: string | (() => any),
    cb: any,
    options?: Record<string, any>
): Function

这是vuejs源码定义,第一个参数是一个表达式,表示要观察的表达式,或者couputed函数在vuejs实例上的变化。

第二个参数是一个回调函数,调用时会从参数得到新数据(new value)和旧数据(old value)。

第三个参数接受一个对象里面可以传deep或者immediate。deep时为了发现对象内部值的变化,可以在参数指定deep:true。不过注意,监听数组变动不需要。
immediate:设置它为true,将立即以表达式当前值触发回调。而不是等到数据变化才触发回调。

vm.$watch返回一个取消观察函数,用来停止触发回调:

var unwatch = vm.$watch('a', (newVal, oldVal) => {});
unwatch() // 之后取消观察

watch的内部原理

vm.【vueJs源码】阅读之vm.$watch函数_前端_02watch的功能。

但vm.$watch中的参数deep和immeditae是watcher中所没有的。

Vue.prototype.$watch = function (
    expOrFn: string | (() => any),
    cb: any,
    options?: Record<string, any>
  ): Function {
    const vm: Component = this
    if (isPlainObject(cb)) {
      return createWatcher(vm, expOrFn, cb, options)
    }
    options = options || {}
    options.user = true
    const watcher = new Watcher(vm, expOrFn, cb, options)
    if (options.immediate) {
      const info = `callback for immediate watcher "${watcher.expression}"`
      pushTarget()
      invokeWithErrorHandling(cb, vm, [watcher.value], vm, info)
      popTarget()
    }
    return function unwatchFn() {
      watcher.teardown()
    }
  }

这是watch的源码。先执行new Watcher来实现vm.$watch的基本功能。

执行完new Wathcer之后,代码判断是否使用immediate参数。如果使用了则立即实行一次cb。

最后,执行一个函数unwatchFn,用来取消观察数据。

实际是执行了teardown()来取消观察数据。是把watcher实例从当前正在观察的状态的依赖列表中移除。