-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwatch深度监听
53 lines (47 loc) · 1.67 KB
/
watch深度监听
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
1. 两种用法 https://cn.vuejs.org/v2/api/#watch
1.1 watch是一个对象,对象的一个个属性是函数
watch: {
d () {}
}
1.2 watch是一个对象,属性还是对象,对象是handle和附加属性
watch: {
d: {
handler: 'someMethod',
immediate: true // 初始化立刻执行一次
deep: true, // 深度监听
},
}
2. 实现原理:参看vue源码initWatch => Vue.prototype.$watch => new Watcher
function initWatch(vm, watch) {
for (let key in watch) {
vm.$watch(key, watch[key].handle, watch[key])
}
}
Vue.prototype.$watch = function (expOrFn, cb, options) {
const vm = this
const watcher = new Watcher(vm, expOrFn, cb, options)
if (watcher.immediate) { // 初始化便执行一次
vm.call(cb, watcher.value)
}
return function unwatch() { // 返回一个函数,用于解除监听
watcher.teardown()
}
}
class Watcher {
constructor (vm, exprOrFn, cb, options, isRenderWatcher) {
this.deep = !!options.deep
this.value = this.get()
this.getter = expOrFn // 该观察者的表达式,用于获取观察者的值
this.cb = cb //监听到变化时,该观察者执行的回调
}
get () {
try {
value = this.getter.call(vm, vm) // 通过expOrFn获取观察者的值。计算过程中触发被观察者的get,从而将该观察者加入对应被观察者的依赖集deps中
}finally () {
if (this.deep) { // 深度监听
traverse(value) // 会对对象中的每一项取值,取值时会执行对应的get方法 case:initWatch时,监听对象是个对象,会将观察者加入被监听对象的每一个属性的deps中
}
}
return value // 返回该观察者的新值
}
}