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
_dirty
To indicate whether or not to cache - 2. Mostly
effect
To 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