Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vue属性发生变化时,如何通知到计算属性一起更新? #3

Open
Diazhao opened this issue Jan 29, 2019 · 1 comment
Open

Comments

@Diazhao
Copy link
Owner

Diazhao commented Jan 29, 2019

No description provided.

@Diazhao
Copy link
Owner Author

Diazhao commented Jan 30, 2019

  1. 经过依赖收集阶段收集到view依赖的属性数据之后
  2. 数据变更会调用 dep.notify()发出变更通知
  3. Dep类中执行notify,调用subs[i].update()。这里的subs就是在依赖收集阶段收集到的实例化的watcher
  4. watcher中的update会执行如下步骤,以this.run为例继续往下分析
    if (this.computed) {
      // A computed property watcher has two modes: lazy and activated.
      // It initializes as lazy by default, and only becomes activated when
      // it is depended on by at least one subscriber, which is typically
      // another computed property or a component's render function.
      if (this.dep.subs.length === 0) {
        // In lazy mode, we don't want to perform computations until necessary,
        // so we simply mark the watcher as dirty. The actual computation is
        // performed just-in-time in this.evaluate() when the computed property
        // is accessed.
        this.dirty = true
      } else {
        // In activated mode, we want to proactively perform the computation
        // but only notify our subscribers when the value has indeed changed.
        this.getAndInvoke(() => {
          this.dep.notify()
        })
      }
    } else if (this.sync) {
      this.run()
    } else {
      queueWatcher(this)
    }
  1. 接下来会执行到const value = this.get(), this.get是依赖变更后更新的核心
  2. 依赖收集阶段会将getter与当前数据绑定。注意到在初始化的时候,new Watcher(vm, updateComponent),这里的updateComponent即为此处调用的getter.这里之后,就是对比虚拟dom,进而更新对应的node
  get () {
    pushTarget(this)
    let value
    const vm = this.vm
    try {
      value = this.getter.call(vm, vm)
    } catch (e) {
      if (this.user) {
        handleError(e, vm, `getter for watcher "${this.expression}"`)
      } else {
        throw e
      }
    } finally {
      // "touch" every property so they are all tracked as
      // dependencies for deep watching
      if (this.deep) {
        traverse(value)
      }
      popTarget()
      this.cleanupDeps()
    }
    return value
  }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant