Vue2的响应式逻辑(Observer,Dep,Wather的关系)

184 阅读4分钟

响应式系统是其核心特性之一,主要涉及到WatcherDep(通常表示依赖)等概念

一、响应式原理概述

Vue 2 使用 Object.defineProperty () 方法将对象的属性转换为 getter 和 setter,从而实现对数据的响应式追踪。当数据被读取时,会收集依赖(通常是Watcher实例);当数据被修改时,会通知依赖进行更新。

二、Watcher

  1. 作用:

    • Watcher是一个观察者,它观察特定的响应式数据,并在数据变化时执行相应的回调函数。通常在计算属性、侦听器以及组件的渲染过程中创建Watcher实例。
    • 例如,在组件的渲染过程中,每个组件实例都会创建一个渲染Watcher,它观察组件的所有响应式数据,当这些数据变化时,触发组件的重新渲染。
  2. 工作过程:

    • 在创建Watcher实例时,它会立即执行其get方法,这个方法会触发响应式数据的 getter,从而收集当前的依赖。

    • Watcher观察的数据发生变化时,会触发它的回调函数,执行相应的更新操作。

  3. 创建时机:

    • vue实例内有watch的时候,initState->initWatch->createWatcher
    • vue实例内有computed的时候,initState->initComputed
    • 逻辑内有vm.$watch的时候,会调用stateMixin->Vue.prototype.$watch
    • 在挂载调用$mounted的时候mountComponent

三、Dep(依赖收集器)

  1. 作用:

    • Dep用于收集依赖,它维护了一个Watcher列表。当响应式数据被读取时,会将当前正在读取数据的Watcher添加到Dep中。
    • 当数据变化时,Dep会通知所有收集到的Watcher进行更新。
  2. 工作过程:

    • 在响应式数据的 getter 中,会创建一个Dep实例(如果不存在的话),并将当前正在读取数据的Watcher添加到Depsubs列表中。
    • 在响应式数据的 setter 中,会遍历Dep中的Watcher列表,通知每个Watcher进行更新。
  3. 创建时机:

    • 把数据转化为响应式的调用栈initState->initData/observe->new Observer->walk/observeArray->defineReactive
    • new Observer的内部
      • 引用数据做响应式,会通过this.dep = new Dep()创建dep的实例,作为Observer实例的实例属性
      • 简单类型数据做响应式,会通过defineReactive函数内的const dep = new Dep()弄一个闭包来保存dep
      • 会通过def(value, '__ob__', this);把这个Observer实例挂载到这个引用数据上面
      • 通过defineReactive会设置getter,内部会有dep.depend()逻辑,用于访问数据的时候,收集相关dep
      • 通过defineReactive会设置setter,内部会有dep.notify()逻辑,用于设置数据的时候,通知所有dep执行所有subsupdate更新视图

四、通知机制

  1. 数据变化触发通知:

    • 当响应式数据被修改时,会触发其 setter。在 setter 中,会通知相关的Dep实例,Dep再通知所有收集到的Watcher进行更新。
    • 例如,当一个响应式数据属性被赋值为新的值时,会触发其 setter,进而通知所有依赖这个属性的Watcher
  2. Watcher的更新过程:

    • Watcher收到通知后,会执行其回调函数。对于渲染Watcher来说,回调函数通常会触发组件的重新渲染。对于计算属性的Watcher来说,回调函数会重新计算计算属性的值。
    • 在更新过程中,可能会再次触发响应式数据的读取,从而收集新的依赖,形成一个更新循环。
  3. 如果没有对应的watcher,则不会收集对应的dep,因为用于保存收集响应式数据的depthis.deps挂载在Wather的实例上(注意,对应的dep是在响应式数据上的,不要与deps弄混)

  4. 如果没有不是响应式数据,自然也不会生成对应的Dep实例,也不会收集对应的wather,因为根本不存在相应的响应式数据的dep(用于收集wathersubs数组,是dep的实例属性)

  5. depsubswatcerdeps是相互收集,对多对的关系

Snipaste_2024-08-23_16-46-01.jpg

Vue 2 的响应式系统通过WatcherDep等机制实现了数据变化的自动检测和视图的自动更新,使得开发者可以专注于业务逻辑,而不必手动管理数据和视图的同步。