Vue响应式依赖收集原理分析-vue高级必备

本文深入探讨Vue的响应式原理,从observe、Observer、Dep和Watcher的角度解析依赖收集过程,详细解释何时触发依赖收集及数据变化时如何进行更新,帮助读者掌握Vue数据响应式的核心机制。
摘要由CSDN通过智能技术生成

背景

在 Vue 的初始化阶段,_init 方法执行的时候,会执行 initState(vm) ,它的定义在 src/core/instance/state.js 中。在初始化 data 和 props option 时我们注意 initProps 和 initData 方法中都调用了 observe 方法。通过 observe (value),就可以将数据变成响应式。

export function initState (vm: Component) {
   
  vm._watchers = []
  const opts = vm.$options
  if (opts.props) initProps(vm, opts.props)
  if (opts.methods) initMethods(vm, opts.methods)
  if (opts.data) {
   
    initData(vm)
  } else {
   
    observe(vm._data = {
   }, true /* asRootData */)
  }
  if (opts.computed) initComputed(vm, opts.computed)
  if (opts.watch && opts.watch !== nativeWatch) {
   
    initWatch(vm, opts.watch)
  }
}
  • initProps

    if (value === undefined) {
         
      observe(value);
    }
    
  • initData

    observe(data, true /* asRootData */)
    

目标

  • 理解 Vue 数据响应式原理,了解响应式原理依赖收集的过程
  • 了解在什么阶段会触发依赖收集

源码解读

入口函数:observe

observe 方法定义在 src/core/observer/index.js 中。如果是一个非 VNode 的对象类型的数据,它会尝试给这个值去创建一个 observer 实例,如果创建成功,返回新的 observer。或者如果 ob 已经存在了,就会直接返回一个现有的 observer。

/** * 尝试给这个值去创建一个 observer 实例,如果创建成功,返回新的 observer  * 或者如果值已经有了,返回一个现有的 observer * @param {*} value  * @param {boolean} asRootData  * @returns Observer | void */
export function observe (value: any, asRootData: ?boolean): Observer | void {
   
  if (!isObject(value) || value instanceof VNode) {
   
    return
  }
  let ob: Observer | void
  // 如果 value 已经有 observer,就返回现有的 observer
  // 否则如果不是服务器渲染,value是数组或者对象,value 是可扩展的,value 不是 vue 实例,就创建一个新的 observer
  if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) {
   
    ob = value.__ob__
  } else if (
    shouldObserve &&
    !isServerRendering() &&
    (Array.isArray(value) || isPlainObject(value)) &&
    Object.isExtensible(value) &&
    !value._isVue
  ) {
   
    ob = new Observer(value)
  }
  // 如果是根组件,vmCount 不为0
  if (asRootData && ob) {
   
    ob.vmCount++
  }
  return ob
}

通过 new Observer(value) 可以给 value 创建一个 observer 实例,那么 Observer 类的定义和作用是什么?在同一个文件下可以看到 class Observer 是如何定义的。

class Observer

Observer 方法定义在 src/core/observer/index.js 中。在它的构造函数中,首先实例化 Dep 对象(主要用来存放它的 watcher列表),接着通过执行 def 函数把自身实例添加到数据对象 value 的 ob 属性上,所以存在 ob 属性意味着已经被观察过。最后判断 value 为数组的情况下,会数组项遍历,给数组的每一项创建一个 observe 实例;如果是对象,那么遍历所有的属性,通过Object.defineProperty修改getter/setters。

/** * Observer 类和每个响应式对象关联。 * observer 会转化对象的属性值的 getter/setters 方法收集依赖和派发更新。 */
export class Observer {
   
  value: any;
  dep: Dep;
  vmCount: number; // number of vms that have this object as root $data

  constructor(value: any) {
   
    this.value = value
    this.dep = new Dep() // 存放 Observer 的 watcher 列表
    this.vmCount = 0
    def(value, '__ob__', this) // __ob__ 指向自身 observe 实例,存在 __ob__ 属性意味着已经被观察过
    // 如果是数组
    if (Array.isArray(value)) {
   
      // hasProto = '__proto__' in {} 判断对象是否存在 __proto__ 属性
      if (hasProto) {
   
        // 如果有 __proto__,就将 value.__proto__ 指向 arrayMethods
        protoAugment(value, arrayMethods)
      } else {
   
        // 否则,就遍历 arrayMethods,将值复制到 value 上
        copyAugment(value, arrayMethods, arrayKeys)
      }
      this.observeArray(value) // 数组项遍历,给数组的每一项创建一个 observe 实例
    } else {
   
      this.walk(value) // 遍历所有的属性,修改 getter/setters
    }
  }

  // 遍历所有的属性,修改 getter/setters,这个方法只有在 value 是object时调用
  walk (obj: Object) {
   
    const keys = Object.keys(obj)
    for (let i = 0; i < keys.length; i++) {
   
      defineReactive(obj, keys[i])
    }
  }

  // 数组项遍历,给数组的每一项创建一个 observe 实例
  observeArray (items: Array<any>) 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值