Skip to content

Commit 8428a3c

Browse files
committed
[update]watch原理分析
1 parent 33acbb7 commit 8428a3c

File tree

4 files changed

+28
-1
lines changed

4 files changed

+28
-1
lines changed

vue/src/core/instance/state.js

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,11 @@ export function initState (vm: Component) {
6464
observe(vm._data = {}, true /* asRootData */)
6565
}
6666
if (opts.computed) initComputed(vm, opts.computed) // 初始化computed
67+
68+
// 这个 nativeWatch 定义在 src/core/util/env.js 中
69+
// Firefox 在对象原型上有一个 watch 方法,感兴趣的可以去 MDN 了解下
6770
if (opts.watch && opts.watch !== nativeWatch) {
68-
initWatch(vm, opts.watch)
71+
initWatch(vm, opts.watch) // 初始化watch
6972
}
7073
}
7174

@@ -313,7 +316,11 @@ function initMethods (vm: Component, methods: Object) {
313316

314317
function initWatch (vm: Component, watch: Object) {
315318
for (const key in watch) {
319+
320+
// 获取属性的处理函数
316321
const handler = watch[key]
322+
323+
// 处理函数如果是数组,遍历每个项调用 createWatcher
317324
if (Array.isArray(handler)) {
318325
for (let i = 0; i < handler.length; i++) {
319326
createWatcher(vm, key, handler[i])
@@ -330,10 +337,13 @@ function createWatcher (
330337
handler: any,
331338
options?: Object
332339
) {
340+
341+
// handler 是个对象,把对象复制给 options,然后再获取 handler 处理函数
333342
if (isPlainObject(handler)) {
334343
options = handler
335344
handler = handler.handler
336345
}
346+
337347
if (typeof handler === 'string') {
338348
handler = vm[handler]
339349
}
@@ -372,12 +382,20 @@ export function stateMixin (Vue: Class<Component>) {
372382
options?: Object
373383
): Function {
374384
const vm: Component = this
385+
386+
// 判断值是对象,接着调用 createWatcher
375387
if (isPlainObject(cb)) {
376388
return createWatcher(vm, expOrFn, cb, options)
377389
}
378390
options = options || {}
391+
392+
// 标志是 user watcher
379393
options.user = true
394+
395+
// 实例化user watcher
380396
const watcher = new Watcher(vm, expOrFn, cb, options)
397+
398+
// 如果 immediate 值为true,立即执行处理函数
381399
if (options.immediate) {
382400
cb.call(vm, watcher.value)
383401
}

vue/src/core/observer/index.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,8 @@ export function defineReactive (
177177
enumerable: true,
178178
configurable: true,
179179
get: function reactiveGetter () {
180+
181+
// 获取 getter 函数,这里就是 src/core/instance/lifecycle.js 的 updateComponent
180182
const value = getter ? getter.call(obj) : val
181183
if (Dep.target) {
182184

@@ -192,6 +194,8 @@ export function defineReactive (
192194
return value
193195
},
194196
set: function reactiveSetter (newVal) {
197+
198+
// 获取 getter 函数,这里就是 src/core/instance/lifecycle.js 的 updateComponent
195199
const value = getter ? getter.call(obj) : val
196200
/* eslint-disable no-self-compare */
197201
if (newVal === value || (newVal !== newVal && value !== value)) {
@@ -202,6 +206,8 @@ export function defineReactive (
202206
customSetter()
203207
}
204208
if (setter) {
209+
210+
// 这就是为什么改响应式数据,能够修改视图
205211
setter.call(obj, newVal)
206212
} else {
207213
val = newVal

vue/src/core/observer/traverse.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ function _traverse (val: any, seen: SimpleSet) {
2424
}
2525
if (val.__ob__) {
2626
const depId = val.__ob__.dep.id
27+
28+
// 遍历过程中会把子响应式对象通过它们的 dep id 记录到 seenObjects,避免以后重复访问
2729
if (seen.has(depId)) {
2830
return
2931
}

vue/src/core/observer/watcher.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ export default class Watcher {
138138
} finally {
139139
// "touch" every property so they are all tracked as
140140
// dependencies for deep watching
141+
// deep watcher
141142
if (this.deep) {
142143
traverse(value)
143144
}

0 commit comments

Comments
 (0)