Vue 源码初探(六)数组依赖收集与触发更新

349 阅读1分钟

思维导图

Vue源码初探.png

前言

上一节Vue 源码初探(五)对象异步更新nextTick()我们处理了对象频繁修改值,把多次操作进行合并处理,其中就是把依赖信息先收集起来放到微任务中一起执行

正文

给引用类型创建dep

class Observer {
  constructor(data) {
    //给每一个监测的对象添加一个__ob__的属性指向自己,可以用来判断当前对象是否已经监测过了。
    // data.__ob__ = this
    //这个属性不能在循环的时候被遍历到
    //希望给一个上新增一个属性,也能更新视图。
    // {name: '小明', age: '10'}.dep => watcher
    this.dep = new Dep()

    Object.defineProperty(data, '__ob__', {
      value: this,
      enumerable: false
    })
  }
}

image.png

引用属性值、数组递归收集依赖(watcher)

Object.defineProperty(data, key, {
    get() {
      if (Dep.target) {  //dep.target 现在保存着watcher
        dep.depend()
        if (childOb) { //取属性的时候 会对对应的值(对象本身和数组)进行依赖收集
          childOb.dep.depend() //让数组和对象也记住当前的watcher
          if(Array.isArray(value)){
            dependArray(value)
          }
        }
      }
      return value
    }
})

image.png

触发更新

const ob = this.__ob__
ob.dep.notify()  //触发页面更新

小结

  1. 默认vue在初始化的时候,会对每一个属性进行劫持,增加dep属性,当取值的时候会进行依赖收集
  2. 默认还会对属性值是(对象和数组本身进行增加dep属性)进行依赖收集
  3. 如果是属性变化 触发属性对应的dep去更新
  4. 如果是数组更新,触发数组本身的dep进行更新
  5. 如果取值的时候是数组还要让数组中的对象类型也进行依赖收集 (递归依赖收集)
  6. 如果数组里面放对象,默认对象里面的属性是会进行依赖收集的,因为在取值的时候会进行JSON.stringify操作。