vue依赖包(vue依赖注入的三种方式)

Vue 依赖收集整体流程其实就是一套「订阅者模式」,收集订阅者,把所有需要监听内容数据,全都收集起来。

每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把“接触”过的数据 property 记录为依赖。之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。 
https://cn.vuejs.org/v2/guide/reactivity.html#%E5%A6%82%E4%BD%95%E8%BF%BD%E8%B8%AA%E5%8F%98%E5%8C%96
之前文章写过 Vue 执行数据监听是重写了 Object.defineProperty 里 get 方法,通过 defineReactive 这个函数来实现数据的收集。
var dep = new Dep();
Object.defineProperty(obj, key, { enumerable: true, configurable: true, get: function reactiveGetter () {    // 获取当前监听的值 const value = getter ? getter.call(obj) : val;    // Dep 在上面已经声明;    // Dep.target 表明是当前哪个 Watcher if (Dep.target) {      dep.depend();// 添加到订阅列表里,方法在 dep.js 文件定义 if (childOb) { childOb.dep.depend() if (Array.isArray(value)) { dependArray(value) } } } return value }})
new Dep() 初始化 Dep 来收集 watcher ,简单来说 Dep 是个「订阅列表」。
get 方法里面:先获取当前值赋值给 value,Dep.target 是静态属性,表明我当前执行的 Watcher 是哪个。Dep 的相关文件定义在 src/core/observer/dep.js
export default class Dep {  static target: ?Watcher;// 静态属性  id: number;// Dep id  subs: Array<Watcher>;// Watcher 列表  constructor () {    this.id = uid++    this.subs = []  }  addSub (sub: Watcher) {    this.subs.push(sub)  }  removeSub (sub: Watcher) {    remove(this.subs, sub)  }  depend () {    if (Dep.target) {      Dep.target.addDep(this)    }  }}
然后去执行 dep.depend() 方法把当前 watcher 添加到 Dep 订阅列表里。depend 方法是在 Dep 类里声明的,而这里的 Dep.target 表示的是当前的 watcher ,而 addDep 方法则是在 watcher 里面声明的,把 dep id 添加到 newDepIds 数组里。
Dep 原型上的方法 addSub 把 watcher 都添加到 subs 里面,每添加一个订阅者 id 都会加 1,用 removeSub 方法来删除 subs 里面对应的 watcher 。
Watcher 相关文件定义在 src/core/observer/watcher.js。
    export default class Watcher {  addDep (dep: Dep) {    const id = dep.id    if (!this.newDepIds.has(id)) {      this.newDepIds.add(id)      this.newDeps.push(dep)      if (!this.depIds.has(id)) {        dep.addSub(this)      }    }  },  get () {    pushTarget(this)  }}
    而 watcher 类实现的就是「订阅者」。
    Watcher 里调用的方法 get 里 pushTarget 方法其实是在 Dep 里面定义的,来把当前的 watcher 添加到 targetStack 栈中,popTarget 则是把 watcher 从 targetStack 中移除,通过这「添加」和「移除」给 Dep.target 来赋值当前 Watcher。
      const targetStack = []export function pushTarget (target: ?Watcher) {  targetStack.push(target)  Dep.target = target}export function popTarget () {  targetStack.pop()  Dep.target = targetStack[targetStack.length - 1]}

      依赖收集的目的为了把 Watcher 收集起来,等触发 getter 的时候,会通知需要更新的 watcher 去执行更新。


      图片授权基于 www.pixabay.com 相关协议

      推荐阅读

      如何用 vue-cli 调试源码?
      如何调试 Vue 源码?

      Vue 在挂载数据前都经历了什么?


      原创文章,作者:小道研究,如若转载,请注明出处:https://www.sudun.com/ask/34516.html

      (0)
      小道研究's avatar小道研究
      上一篇 2024年4月14日 上午8:09
      下一篇 2024年4月14日 上午8:11

      相关推荐

      发表回复

      您的邮箱地址不会被公开。 必填项已用 * 标注