vue源码阅读之Watcher类

我们上次分析vue源码讲的是收集依赖,数据变化之后我们把依赖收集到dep类中,通过这个管理器进行管理。

里面有一个subs数组,用来存放依赖,并且定义了几个实例方法用来依赖进行添加,删除,通过操作。

比如addSub,removeSub,depend、notify等方法。

依赖到底是谁

我们dep是用来管理依赖的,那么要添加的依赖到底是谁?

其实这个依赖就是我们常说的watcher的类,也就是说谁用了数据,谁就是那个依赖。

谁用到了数据,我们就为谁创建一个Watcher实例。在之后数据变化的时候,我们不去直接通知依赖更新,而是通知依赖对应的Watch实例,由Watcher实例去通知真正的视图。

export default class Watcher implements DepTarget {
}

这个就是Watcher类,实现了DepTarget。
而DepTarget这个接口在dep类里面实现的。

export interface DepTarget extends DebuggerOptions {
  id: number
  addDep(dep: Dep): void
  update(): void
}

Wathcer构造函数

下面是Watcher构造函数的源码。

constructor(
    vm: Component | null,
    expOrFn: string | (() => any),
    cb: Function,
    options?: WatcherOptions | null,
    isRenderWatcher?: boolean
  ) {
    // 初始化代码
    // 此处省略部分代码...
    this.value = this.lazy ? undefined : this.get()
  }

这个就是在创建Watcher实例的时候初始执行的部分。在创建Watcher实例的时候会自动把自己添加到这个数据的依赖管理器中。

在最后一行有个this.value,执行了this.get();

这个get函数源码如下

 get() {
    pushTarget(this)
    let value
    const vm = this.vm
    try {
      value = this.getter.call(vm, vm)
    } catch (e: any) {
      if (this.user) {
        handleError(e, vm, `getter for watcher "${this.expression}"`)
      } else {
        throw e
      }
    } finally {
      // "touch" every property so they are all tracked as
      // dependencies for deep watching
      if (this.deep) {
        traverse(value)
      }
      popTarget()
      this.cleanupDeps()
    }
    return value
  }

这里get函数第一步就是把这个watcher实例给了Dep.target。

然后在通过this.getter.call(vm, vm)获取一下被依赖的数据,这里的getter就是

更新组件重新传染函数updateComponent。

当数据发生变化的时候,会触发set函数,set函数接着会触发dep.nofity函数。然后执行Watcher类中的update()方法,调用数据变化的更新回调函数,从而更新视图。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值