浅析 computed

computed

⭐️ 计算属性就是对data里面的数据进行计算得到的一个新的属性。它依赖于用于计算的数据,模板近似于函数调用,那么它和函数有什么区别,内部又是怎么实现的,让我们一起来探索一下计算属性。

计算属性和函数有什么区别

  1. 在使用时,computed可以作为属性,而函数则当做方法调用
  2. computed可以配置gettersetter,因此可以赋值,而函数不行
  3. computed无法接收多个参数,而函数可以
  4. computed具有缓存,而函数没有

接下来深入了解一下 computed 是怎么实现的吧。

初始化computed

function initComputed (vm: Component, computed: Object) {
  const watchers = vm._computedWatchers = Object.create(null)
  for (const key in computed) {
    const userDef = computed[key]
    const getter = typeof userDef === 'function' ? userDef : userDef.get
    // component-defined computed properties are already defined on the
    // component prototype. We only need to define computed properties defined
    // at instantiation here.
    if (!(key in vm)) {
      defineComputed(vm, key, userDef)
    }
  }
}

function initWatch (vm: Component, watch: Object) {
  for (const key in watch) {
    const handler = watch[key]
    if (Array.isArray(handler)) {
      for (let i = 0; i < handler.length; i++) {
        createWatcher(vm, key, handler[i])
      }
    } else {
      createWatcher(vm, key, handler)
    }
  }
}

🌈当初始化computed时,为每一个属性创建一个Watcher对象,通过Object.defineProperty配置gettergetter运行过程中就会收集依赖。

⭐️但是计算属性的Watcher不会立即执行,要看模板中是否有使用到该计算属性,也就是依赖该计算属性,如果模板中没有使用,Watcher就不会去执行。由于,在给每个属性创建Watcher实例的时候,Vue配置了lazy,可以让Watcher不立即执行。

实现缓存

Watcher内部维护两个属性用来做缓存:valuedirty

  1. value属性用于保存Watcher运行的结果,受lazy的影响,value 在最开始是undefined
  2. dirty属性用于指示当前的value是否为脏值,受lazy的影响,该值在最开始是true
const computedWatcherOptions = { lazy: true }

function createComputedGetter (key) {
  return function computedGetter () {
    const watcher = this._computedWatchers && this._computedWatchers[key]
    if (watcher) {
      if (watcher.dirty) {
        watcher.evaluate()
      }
      if (Dep.target) {
        watcher.depend()
      }
      return watcher.value
    }
  }
}

工作流程

⭐️当页面依赖计算属性时,vue首先检查其对应的Watcher中的dirty属性,判断该值是否是脏值,如果是,则运行getter进行计算,并得到对应的值,保存在Watchervalue中,然后把Watcher中的dirty改为false,然后返回。如果多次使用属性,也是先判断该值是否为脏值,如果不是脏值,直接读取value值,做到数据缓存。
⭐️当计算属性的依赖数据变化时,就会先触发计算属性的Watcher运行,把dirty配置改为true,不做任何处理。当组件渲染的时候,重新读取计算属性,dirtytrue,因此会重新运行getter进行计算、缓存。

⭐️扩展阅读:

  1. 浅析 v-node 👉 猛戳这里
  2. vue2 响应式原理 👉 猛戳这里
  3. 浅析 keep-alive 👉 猛戳这里
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值