JS中的依赖关系跟踪功能



at vue.js的高级功能从头开始 evan做出了一点任务。

  • 使用两种方法创建Dep类:dependnotify
  • 创建一个autorun功能,该功能采用更新器功能。
  • 在更新器功能中,您可以通过调用dep.depend()
  • 明确地取决于Dep的实例
  • 稍后,您可以触发更新程序功能,以再次调用dep.notify()

全部用法应该像这样:

const dep = new Dep()
autorun(() => {
  dep.depend()
  console.log('updated')
})
// should log: "updated"
dep.notify()
// should log: "updated"

该任务的想法是在vue中显示依赖性的逻辑。

解决方案

<script>
// a class representing a dependency
// exposing it on window is necessary for testing
window.Dep = class Dep {
    constructor () {
      this.subscribers = new Set()
    }
    depend () {
      if (activeUpdate) {
        // register the current active update as a subscriber
        this.subscribers.add(activeUpdate)
      }
    }
    notify () {
      // run all subscriber functions
      this.subscribers.forEach(subscriber => subscriber())
    }
}
let activeUpdate
function autorun (update) {
  function wrappedUpdate () {
    activeUpdate = wrappedUpdate
    update()
    activeUpdate = null
  }
  wrappedUpdate()
}
</script>

我不明白为什么我们在代码中使用activeUpdatewrappedUpdate。埃文解释说

我们正在将wrappedUpdate注册为activeUpdate,因此当我们的依赖性更改并且update函数再次称为时,我们实际上再次调用wrappedUpdate。我们需要使我们的小依赖技巧仍在进行未来的迭代效果,并且不断收集所有依赖性。这很重要,因为在某些情况下,我们的update函数可能包含条件(如果true-此依赖关系,则false-其他)。我们的依赖收集系统应动态重新平衡,并始终保持依赖关系的最新状态。

任何人都可以解释它如何工作?

首先,我们在这里没有提升/时间死区问题。由于dep.depend()始终会在全局范围中找到activeUpdate变量,除非我们在声明该变量之前调用该方法。

为什么activeUpdate

对于正确的依赖性跟踪,我们需要一个工具来指示我们在当前正在运行的功能中。这就是使用activeUpdate变量的重点 - 以表示我们在wrappedUpdate功能中,我们即将更新依赖关系。

为什么wrappedFunction

我们希望在调用依赖关系和update函数时,请检查一下新的订户。它看起来像是一系列电话:

notify-->包装update-> dep.depperdeviprate()

通过activeUpdate,我们检查我们的依赖性是否由于某些条件而更改。如果有 - 我们将其注册在 subscriber Set 中,如果它已经在Set中 - 我们忽略了添加。

最新更新