//移除订阅者,把 Watcher 从 subs 中移除。 //由于移除订阅者的操作可能会影响到遍历 subs,所以这里采用了标记位的方式,把要移除的 Watcher 标记为 null,然后在下一次 scheduler flush 的时候再进行清除。 removeSub(sub: DepTarget) { // #12696 deps with massive amount of subscribers are extremely slow to // clean up in Chromium // to workaround this, we unset the sub for now, and clear them on // next scheduler flush. this.subs[this.subs.indexOf(sub)] = null if (!this._pending) { this._pending = true pendingCleanupDeps.push(this) } } //收集依赖,把当前的 Watcher 添加到该 Dep 实例的 subs 中。 //如果有需要调试的信息(如 onTrack 回调函数),则调用该回调函数。 depend(info?: DebuggerEventExtraInfo) { if (Dep.target) { Dep.target.addDep(this) if (__DEV__ && info && Dep.target.onTrack) { Dep.target.onTrack({ effect: Dep.target, ...info }) } } }
//通知更新,当一个 Dep 实例被更新时,它会遍历 subs 中的所有 Watcher,并依次调用它们的 update 方法进行更新。 //在这个过程中,如果有需要调试的信息(如 onTrigger 回调函数),则调用该回调函数。 //如果配置中不是异步模式,则需要对 subs 进行排序以确保它们按正确的顺序触发更新。 notify(info?: DebuggerEventExtraInfo) { // stabilize the subscriber list first const subs = this.subs.filter(s => s) asDepTarget[] if (__DEV__ && !config.async) { // subs aren't sorted in scheduler if not running async // we need to sort them now to make sure they fire in correct // order subs.sort((a, b) => a.id - b.id) } for (let i = 0, l = subs.length; i < l; i++) { const sub = subs[i] if (__DEV__ && info) { sub.onTrigger && sub.onTrigger({ effect: subs[i], ...info }) } sub.update() } } }
继续看
1 2 3 4 5 6 7 8 9 10
constpendingCleanupDeps: Dep[] = []
exportconstcleanupDeps = () => { for (let i = 0; i < pendingCleanupDeps.length; i++) { const dep = pendingCleanupDeps[i] dep.subs = dep.subs.filter(s => s) dep._pending = false } pendingCleanupDeps.length = 0 }
// The current target watcher being evaluated. // This is globally unique because only one watcher // can be evaluated at a time. Dep.target = null consttargetStack: Array<DepTarget | null | undefined> = []