手写mini版本的Vue3--实现 computed 计算属性

315 阅读1分钟

介绍

开头继续感谢崔大的mini-vue 项目。

项目地址:github.com/cuixiaorui/…

强烈建议大家把项目 down 下来,运行一下,看VUE3 的整体运行逻辑。

实现 computed

computed 这个跟 ref 差不多,都是通过.value的形式调用。

computed 特有的功能就是有缓存。

首先我们创建一个 computed 的文件并导出computed 这个函数。

我们要实现的逻辑都在ComputedRefImpl这个类里面实现。

export function computed(getter) {
  return new ComputedRefImpl(getter)
}

以下就是一个简单的 getter的逻辑,获取值的时候,直接返回 getter。

class ComputedRefImpl {
  private _getter:any
  constructor(getter) {
   this._getter = getter
  }

  get value() {
    return this._getter
  }
}

接下来比较重要的 computed 的特性,缓存我们用一个变量 dirty 来判断。

这个时候,我们第一次调用 get value 的时候,就用 _value 这个变量把值给缓存起来,第二次调用的时候,直接返回_value

class ComputedRefImpl {
  private _getter:any
  private _dirty:boolean = true
  private _value:any
  constructor(getter) {
   this._getter = getter
  }

  get value() {
   if(this._dirty) {
   this._dirty = false 
   
    this.value =this._getter()
   }
    return this._value
  }
}

接下来我们要实现的最关键的一步。

也就是当依赖的响应式数据改变的时候,我们重新去触发一下 computed 的属性。

也就是我们需要引入 effect

this._effect = new ReactiveEffect(getter)

把ReactiveEffect 从 reactive 里面导出来。

当this._dirty 是 true 的 时候,我们就去执行 effect 的 run 方法,也就是把用户想要执行的函数放进去执行。

最后一步也就是利用 schedule 的这个方法,当this._dirty 是 false 的时候,把它改成 true

class ComputedRefImpl {
  private _dirty: boolean = true;
  private _value: any;
  private _effect: any;
  constructor(getter) {
    this._effect = new ReactiveEffect(getter, () => {
      if (!this._dirty) {
        this._dirty = true
      }
    })
  }

  get value() {
    if (this._dirty) {
      this._dirty = false
      this._value = this._effect.run()
    }
    return this._value
  }
}

结尾

项目已经放到我的 GitHub 上面了,欢迎大家去start。

本次 commit地址:github.com/moyuhaokan/…

我的项目地址:github.com/moyuhaokan/…

再次推荐崔大的项目:github.com/cuixiaorui/…