preface

Computed properties, you use it a lot in vUE projects. How does computed properties work in VUE3? How does this work if the evaluated property does not change and the function is not called again? Let’s do our simple implementation of computed!

implementation

First, computed in VUe3 is a function, and it takes a parameter, let’s call it getterOrOptions, which can be a function (getter) or an object (getter and setter). A call to computed returns a ComputedRefImpl instance

// computed.ts
/** * cpmputed function *@param GetterOrOptions Getters or options configuration *@returns * / ComputedRefImpl instance
export const computed  = (getterOrOptions) = > {
    let getter;
    let setter;
    // if it is a function
    const onlyGetter = isFunction(getterOrOptions)
    if(onlyGetter) {
      getter = getterOrOptions
      // The setter warns ⚠️
      setter = () = > {
        console.warn('Write operation failed: computed value is readonly')}}else {
      getter = getterOrOptions.get
      setter = getterOrOptions.set
    }
    const cRef = new ComputedRefImpl(getter, setter)
    return cRef
}
Copy the code

The next step is to implement ComputedRefImpl

/ / ComputedRefImpl instance
class ComputedRefImpl {
  public _dirty = true // Defaults to true (as an indication of whether to cache or not)
  public _value
  public effect
  constructor( getter, public setter) {
    // effect can collect dependencies and trigger dependencies,
      this.effect = effect(getter, {
        lazy: true.scheduler: () = > {
          if(!this._dirty) {
            this._dirty = true
            trigger(this, TriggerOrTypes.SET, 'value') // Trigger dependencies to update}}})}get value() {
    // If it is dirty, we execute effect, that is, execute the function passed by the user and return the value to this._value
    if(this._dirty) {
      this._value = this.effect()
      this._dirty = false
    }
    // The. Value dependencies are collected here mainly for implementation, and effect retriggers dependencies and dependency updates when computed depends on properties that change
    track(this, trackOpTypes.GET, 'value') // Collect dependencies using.value
    return this._value
  }
  set value(newVal) {
    this.settet(newVal)
  }
}
Copy the code

Several points to pay attention to when implementing ComputedRefImpl:

  • 1. By_dirtyTo indicate whether or not to cache
  • 2. MostlyeffectTo implement the internal logic,See the effect

test

<! DOCTYPEhtml>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app"></div>
    <script src=".. /node_modules/@vue/reactivity/dist/reactivity.global.js"></script>
    <script>
      let { ref, effect, computed } = VueReactivity
      // Test basic functionality (single GET)
      // const count = ref(1)
      // const plusOne = computed(() => count.value + 1)
      // console.log(plusOne.value) // 2

      // Test basic function 2(get and set usage)
      // const count = ref(1)
      // const plusOne = computed({
      // get: () => count.value + 1,
      // set: (val) => {
      // count.value = val - 1
      / /}
      // })
      // // debugger
      // plusOne.value = 1
      // console.log(count.value) // 0

      // Test basic function 3(dependent properties change, corresponding calculated properties also change)
      const count = ref(1)
      const plusOne = computed(() = > count.value + 1)
      effect(() = > {
        console.log(plusOne.value ); // Dependencies collect.value
      })
      debugger
      count.value = 10  
    </script>
  </body>
</html>
Copy the code

You can use the above examples to test computed that we have written, and if you have run our examples, you can see that the basic functions of computed have been implemented

Vue3 source code implementation series

Vue3 source code – Reactive data Reactive

Vue3 source-effect relies on collecting triggered updates

Vue3 source code – ref article

Vue3 source code – toRef and toRefs

Vue3 source code – Computed