- 用法
- vm.$watch( expOrFn, callback, [options] )
- 功能
- 观察 Vue 实例变化的一个表达式或计算属性函数。回调函数得到的参数为新值和旧值。表达式只 接受监督的键路径。对于更复杂的表达式,用一个函数取代。
- 参数
- expOrFn:要监视的 $data 中的属性,可以是表达式或函数
- callback:数据变化后执行的函数
- 函数:回调函数
- 对象:具有 handler 属性(字符串或者函数),如果该属性为字符串则 methods 中相应 的定义
- options:可选的选项
- deep:布尔类型,深度监听
- immediate:布尔类型,是否立即执行一次回调函数
三种类型的 watcher 对象
- 没有静态方法,因为 $watch 方法中要使用 Vue 的实例
- Watcher 分三种:计算属性 Watcher、用户 Watcher(侦听器)、渲染 Watcher
- 创建顺序:计算属性 Watcher、用户 Watcher(侦听器)、渲染 Watcher
- vm.$watch()
- src\core\instance\state.js
源码
Vue.prototype.$watch = function (
expOrFn: string | Function,
cb: any,
options?: Object
): Function {
// 获取 Vue 实例 this
const vm: Component = this
if (isPlainObject(cb)) {
// 判断如果 cb 是对象执行 createWatcher
return createWatcher(vm, expOrFn, cb, options)
}
options = options || {}
// 标记为用户 watcher
options.user = true
// 创建用户 watcher 对象
const watcher = new Watcher(vm, expOrFn, cb, options)
// 判断 immediate 如果为 true
if (options.immediate) {
// 立即执行一次 cb 回调,并且把当前值传入
try {
cb.call(vm, watcher.value)
} catch (error) {
handleError(error, vm, `callback for immediate watcher "${watcher.expression}"`)
}
}
// 返回取消监听的方法
return function unwatchFn () {
watcher.teardown()
}
}
调试
查看渲染 watcher 的执行过程
- 当数据更新,defineReactive 的 set 方法中调用 dep.notify()
- 调用 watcher 的 update()
- 调用 queueWatcher(),把 wacher 存入队列,如果已经存入,不重复添加
- 循环调用 flushSchedulerQueue()
- 通过 nextTick(),在消息循环结束之前时候调用 flushSchedulerQueue()
- 调用 wacher.run()
- 调用 wacher.get() 获取最新值
- 如果是渲染 wacher 结束
- 如果是用户 watcher,调用 this.cb()