Vue.js 依赖收集

为什么要依赖收集

先看下面这段代码

  • new Vue({
  • template:
  • `<div>
  • <span>text1:</span> {{text1}}
  • <span>text2:</span> {{text2}}
  • <div>`,
  • data: {
  • text1: 'text1',
  • text2: 'text2',
  • text3: 'text3'
  • }
  • });

按照之前《响应式原理》中的方法进行绑定则会出现一个问题—— text3 在实际模板中并没有被用到,然而当 text3 的数据被修改的时候(this.text3 = 'test')的时候,同样会触发text3的setter导致重新执行渲染,这显然不正确。

先说说 Dep

当对 data 上的对象进行修改值的时候会触发它的 setter,那么取值的时候自然就会触发 getter 事件,所以我们只要在最开始进行一次 render,那么所有被渲染所依赖的 data 中的数据就会被 getter 收集到 Dep 的 subs 中去。在对 data 中的数据进行修改的时候 setter 只会触发 Dep 的 subs 的函数。

定义一个依赖收集类 Dep。

  • class Dep () {
  • constructor () {
  • this.subs = [];
  • }
  • addSub (sub: Watcher) {
  • this.subs.push(sub)
  • }
  • removeSub (sub: Watcher) {
  • remove(this.subs, sub)
  • }
  • notify () {
  • // stabilize the subscriber list first
  • const subs = this.subs.slice()
  • for (let i = 0, l = subs.length; i < l; i++) {
  • subs[i].update()
  • }
  • }
  • }

Watcher

订阅者,当依赖收集的时候会 addSub 到 sub 中,在修改 data 中数据的时候会触发Watcher 的 notify,从而回调渲染函数。

top Created with Sketch.