JS中的依赖跟踪功能

时间:2017-09-14 10:38:23

标签: javascript vue.js

Vue.js从头开始的高级功能 Evan做了一个小任务。

  
      
  • 使用两种方法创建Dep课程:dependnotify
  •   
  • 创建一个带有更新程序功能的autorun函数。
  •   
  • 在更新程序功能中,您可以通过调用Dep
  • 明确依赖dep.depend()的实例   
  • 稍后,您可以通过调用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 - 另一个)。我们的依赖性收集系统应该动态地重新平衡并始终保持依赖性是最新的。

任何人都可以解释它是如何运作的吗?

1 个答案:

答案 0 :(得分:0)

首先,我们这里没有吊装/暂时死区问题。因为dep.depend()总是在全局范围内找到activeUpdate变量,除非我们在声明该变量之前调用该方法。

  

为什么activeUpdate

为了正确的依赖关系跟踪,我们需要一个工具来指示我们在当前正在运行的函数内部。这是使用activeUpdate变量的信号 - 表示我们在wrappedUpdate函数内,我们即将更新我们的依赖项。

  

为什么wrappedFunction

我们想要在我们的依赖项更改并调用update函数时检查新订阅者。它看起来像一连串的电话:

  

通知 - &gt; wrappedUpdate - &gt; dep.depend()

并通过activeUpdate检查我们的依赖关系是否因某些条件而被更改。如果有 - 我们在订阅者Set 中注册,如果它已经在Set中 - 我们会忽略添加。