Vue2.x源码学习笔记(八)——实例方法(数据篇)

95 阅读1分钟

在/src/core/instance/state.js中的stateMixin函数里我们在Vue原型上挂在了$delete,$set和$watch方法。

vm.$delete

Vue.prototype.$delete = del

del方法请看第Vue2.x源码学习笔记(七)

vm.$set

Vue.prototype.$set = set

set方法请看第Vue2.x源码学习笔记(七)

vm.$watch

Vue.prototype.$watch = function (
    expOrFn: string | Function,
    cb: any,
    options?: Object
  ): 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) {
      try {
        cb.call(vm, watcher.value)
      } catch (error) {
        handleError(error, vm, `callback for immediate watcher "${watcher.expression}"`)
      }
    }
    return function unwatchFn () {
      watcher.teardown()
    }
  }
function createWatcher (
  vm: Component,
  expOrFn: string | Function,
  handler: any,
  options?: Object
) {
  if (isPlainObject(handler)) {
    options = handler
    handler = handler.handler
  }
  if (typeof handler === 'string') {
    handler = vm[handler]
  }
  return vm.$watch(expOrFn, handler, options)
}

对于第二个参数cb,我们会进行兼容式处理:如果cb是一个对象,我们会把这个的对象的handler函数作为第二个参数。options如果不传,则配置都为false。

然后将这个watcher标记为用户watcher。通过new Watcher创建一个Watcher实例。如果options中immediate为true,则立即执行第二个参数:cb函数。

最后返回一个函数,执行watcher的teardown方法,取消监听。

watcher.teardown()

class Watcher{
  ......
  teardown () {
    if (this.active) {
      if (!this.vm._isBeingDestroyed) {
        remove(this.vm._watchers, this)
      }
      let i = this.deps.length
      while (i--) {
        this.deps[i].removeSub(this)
      }
      this.active = false
    }
  }
}

将本身这个watcher从当前实例的watchers列表中删除。watcher之前有维护一个deps数组用于记录哪些deps依赖中保存了当前watcher。将这些dep的subs数组(存放watcher数组)中的当前watcher移除。