触发更新时watcher的执行
- watcher分为三种,Computed Watcher, 用户Watcher侦听器,渲染Watcher
- 前两种 initState 时初始化
- 渲染watcher在 core/instance/lifecycle.js 中 mountComponent,后执行
- 当调用 dep.notify 时,会对watcher排序,然后依次更新watcher.update
- 对于不同类型 watcher, update处理方式不同
- 渲染watcher会判断 当前组件watcher是否放入队列中,未放入 则找到位置插入到队列中
调用 flushSchedulerQueue 方法
- 先更新父组件后更新子组件(父组件先创建)
- 用户watchers在渲染watcher之前运行,(用户或计算属性在initState中创建,在mountComponent之前)
- 如果一个组件在父组件执行期间被销毁,则跳过当前组件
- 遍历队列中的 watcher,调用 watcher.run()
- run 方法内 调用get 方法, get方法调用 了 this.getter.call(vm, vm)
- this.getter 就是 updateComponent 方法
- 更新结束后重置状态
调用 activated,updated两个钩子
notify () { // copy const subs = this.subs.slice() if (process.env.NODE_ENV !== 'production' && !config.async) { // 按watcher的创建顺序排序 subs.sort((a, b) => a.id - b.id) } // 调用 watcher的 更新 for (let i = 0, l = subs.length; i < l; i++) { subs[i].update() } }
update () { // 三种watcher update 渲染watcher 走else if (this.lazy) { this.dirty = true } else if (this.sync) { this.run() } else { queueWatcher(this) } }
export function queueWatcher (watcher: Watcher) { const id = watcher.id // has是个对象,防止 watcher被重复处理 if (has[id] == null) { has[id] = true // flushing = true 表示 watcher对象正在被处理 // 把watcher放入队列中 if (!flushing) { queue.push(watcher) } else { let i = queue.length - 1 // 队列未处理完,从后向前取watcher和当前组件watcher比较,确定i while (i > index && queue[i].id > watcher.id) { i-- } // 把组件watcher插入对应位置 queue.splice(i + 1, 0, watcher) } // waiting = true 表示 当前队列正在执行 if (!waiting) { waiting = true if (process.env.NODE_ENV !== 'production' && !config.async) { // 遍历所有watcher,调用 watcher.run() flushSchedulerQueue() return } // 生产环境会传入nextTick, nextTick(flushSchedulerQueue) } } }
function flushSchedulerQueue () { ... // 把watcher插入队列 // 遍历队列内的watcher执行 run watcher.run() ... }
run () { ... this.get() // this指watcher ... }
get () { pushTarget(this) ... // this.getter 为 updateComponent value = this.getter.call(vm,vm) }
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。