watch
initWatch
组件选项对象里存在watch
选项open in new window,在组件初始化状态数据的最后,将初始化watch
数据。
初始化watch
就是为watch
选项里的每一项调用vm.$watch
方法创建一个 Watcher。
需要注意的是,watch
的key
对应的value
的形式有多种:
- 函数
- 组件的方法名
- 对象,至少包含
handler
方法,可以有depp
属性和immediate
属性 - 数组,元素是函数
function initWatch (vm: Component, watch: Object) {
for (const key in watch) {
const handler = watch[key]
if (Array.isArray(handler)) {
for (let i = 0; i < handler.length; i++) {
createWatcher(vm, key, handler[i])
}
} else {
createWatcher(vm, key, handler)
}
}
}
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)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
vm.$watch()
在导出Vue
构造函数之前,会先调用stateMixin(Vue)
为其添加一些原型方法,比如$watch
。
// src/core/instance/state.js
export function stateMixin (Vue: Class<Component>) {
// ...
Vue.prototype.$watch = function (
expOrFn: string | Function,
cb: any,
options?: Object
): Function {
const vm: Component = this
// cb 可以包含在 options 里,此处处理 $watch(expOrFn, options)的情况
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) {
// 立即执行回调
cb.call(vm, watcher.value)
}
// 返回取消监听函数
return function unwatchFn () {
watcher.teardown()
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
通过$watch
创建的 Watcher 实例,其options
参数的user
属性为true
,以区分出是用户创建的 Watcher 还是 Vue 内部创建的 Watcher。