三个阶段\
以下面代码为例:\
<script setup>
import {ref, computed} from "vue";
let aaa = ref(100);
function Num() {
aaa.value++
}
let acomputed = computed(() => {
return `computed:` + aaa.value
})
</script>
<template>
<div class="wrapper">
<div v-on:click="Num">Father</div>
<p>{{ acomputed }}</p>
</div>
</template>
打包在内存中的vue文件(只截了template部分):
一、定义阶段
通过computed函数进入,getter即定义comNumber时的入参,创建ComputedRefImpl实例的时候也会创建一个ReactiveEffect实例(计算属性effect),后续执行render的过程也会创建响应式的ReactiveEffect实例(响应式effect)
二、收集阶段
执行_sfc_render过程访问到$setup.acomputed(即我们创建的ComputedRefImpl实例),触发get value
run()函数指向的是computed实例的getter也是我们定义acomputed是入参的函数,此函数执行的时候会获取计算属性的结果
执行trackEffect函数(入参的activeEffect是 响应式effect),把 响应式effect放在ref2.dep中(ref2即acomputed),
三、触发阶段
执行aaa.value++的时候触发aaa实例的set value,拿到aaa.dep(保存的是计算属性effect),执行effect.trigger()(acomputed.dep中存的是响应式effect)会把响应式函数update放在队列里后面触发更新
更新的时候会执行sfc_render重新生成vnode,此过程会再次访问$setup.acomputed,重新获取一次计算属性值
这里通过dirty判断要不要重新获取