“This is the 10th day of my participation in the Gwen Challenge.

Mentioned in this paper,

Through previous learning, we have built a basic responsive implementation through Proxy + Reflect, and explored the principle and implementation of REF.

  • Vue3 Responsivity principle Exploration Part 1-20 lines of code to achieve responsivity
  • Vue3 Principle exploration of response Formula Part 2 – Response formula of multiple structures
  • Vue3 Response type principle exploration Part 3 – Proxy + Reflect + activeEffect
  • Vue3 response formula principle exploration Part 4-REF principle and implementation

In this article, we’ll learn about the implementation of Computed Values.

The computed usage

Going back to the example code for ref:

let param = reactive({ width: 5.height: 2  });
let size = 0;
let newWidth = ref(0);

effect(() = > {
    newWidth.value = param.width * 2;
});

effect(() = > {
    size = newWidth.value * param.height;
});
Copy the code

If you are already familiar with Vue3, you will be more comfortable with the concise usage below.

 let param = reactive({ width: 5.height: 2  });
        
let newWidth = computed(() = > {
    return param.width * 2
});

let size = computed(() = > {
    return newWidth.value * param.height
});

Copy the code

It is relatively simple and elegant, using only a computed package and assigning values once, and fetching.value when you use it.

The computed to realize

function computed(getter) {
  let result = ref()  // Create a new response reference

  effect(() = > (result.value = getter())) // When effect is called, assign the return value from the getter to result.value,

  return result // Return a reference
}
Copy the code

Very neat. The overall code is as follows:

const targetMap = new WeakMap(a);let activeEffect = null // The active effect running

function track(target, key) {
    if(! activeEffect)return;
    let depsMap = targetMap.get(target);
    if(! depsMap) { targetMap.set(target, (depsMap =new Map()));
    }
    let dep = depsMap.get(key);
    if(! dep) { depsMap.set(key, (dep =new Set()));
    }
    dep.add(activeEffect);
}
function trigger(target, key) {
    const depsMap = targetMap.get(target);
    if(! depsMap)return;
    let dep = depsMap.get(key);
    if (dep) {
        dep.forEach(element= >{ element(); }); }}function reactive(target) {
    const handler = {
        get(target, key, receiver) {
            let result = Reflect.get(target, key, receiver);
            track(target, key);
            return result;
        },
        set(target, key, value, receiver) {
            let oldValue = target[key];
            let result = Reflect.set(target, key, value, receiver);
            if(result && oldValue ! = value) { trigger(target, key); }returnresult; }}return new Proxy(target, handler);
}

function ref(raw) {
    const r = {
        get value() {
            track(r, 'value')
            return raw
        },
        set value(newVal) {
            raw = newVal
            trigger(r, 'value')}},return r
}

function effect(eff) {
    activeEffect = eff  // Set this as the activeEffect
    activeEffect()      // Run it
    activeEffect = null // Unset it
}

function computed(getter) {
    let result = ref()  // Create a new reactive reference

    effect(() = > (result.value = getter())) // Set this value equal to the return value of the getter

    return result // return the reactive reference
}

let param = reactive({ width: 5.height: 2  });

let newWidth = computed(() = > {
    return param.width * 2
});

let size = computed(() = > {
    return newWidth.value * param.height
});

Copy the code

Executing the following code will console the expected result.


console.log(`newWidth is ${newWidth.value}, size is ${size}`); // newWidth is 10, size is 20

param.width = 6;

console.log(`newWidth is ${newWidth.value}, size is ${size}`); // newWidth is 12, size is 24
Copy the code

Vue3 source small analysis

We’ve built a responsive system (well, a very weak version of it…). . In the real version of Vue, it’s N times more complex than that. We can briefly list the responsive implementation files in the Vue source code.

The main directory is github.com/vuejs/vue-n… .

The main structure is as follows (as of June 10, 2021) :

Interested students can directly read the source code.

summary

  • computedThe usage is more concise and elegant
  • computedThe encapsulation implementation is based onrefreactivefunction