在/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移除。