/** * Push a watcher into the watcher queue. * Jobs with duplicate IDs will be skipped unless it's * pushed when the queue is being flushed. */ exportfunctionqueueWatcher(watcher: Watcher) { // 属性更新的时候,需要进行入队,也就是说这个 watcher 资源需要更新了 const id = watcher.id if (has[id] != null) { // 通过 id 去重 return }
if (watcher === Dep.target && watcher.noRecurse) { return }
has[id] = true if (!flushing) { queue.push(watcher) // 队列,直接任务入队 } else { // if already flushing, splice the watcher based on its id // if already past its id, it will be run next immediately. let i = queue.length - 1 while (i > index && queue[i].id > watcher.id) { i-- } queue.splice(i + 1, 0, watcher) } // queue the flush if (!waiting) { waiting = true
/** * Flush both queues and run the watchers. */ functionflushSchedulerQueue() { currentFlushTimestamp = getNow() flushing = true let watcher, id
// Sort queue before flush. // This ensures that: // 1. Components are updated from parent to child. (because parent is always // created before the child) // 2. A component's user watchers are run before its render watcher (because // user watchers are created before the render watcher) // 3. If a component is destroyed during a parent component's watcher run, // its watchers can be skipped. queue.sort(sortCompareFn)
// do not cache length because more watchers might be pushed // as we run existing watchers for (index = 0; index < queue.length; index++) { watcher = queue[index] if (watcher.before) { watcher.before() } id = watcher.id has[id] = null watcher.run() // in dev build, check and stop circular updates. if (__DEV__ && has[id] != null) { // :在开发环境中,检查并防止循环更新。如果观察者的 ID 再次被标记为非空,表示发生了循环更新。 circular[id] = (circular[id] || 0) + 1 if (circular[id] > MAX_UPDATE_COUNT) { warn( 'You may have an infinite update loop ' + (watcher.user ? `in watcher with expression "${watcher.expression}"` : `in a component render function.`), watcher.vm ) break } } }
// keep copies of post queues before resetting state const activatedQueue = activatedChildren.slice() // 包含所有在本次调度过程中被激活的组件。 const updatedQueue = queue.slice() // 本次调度中被更新的组件