1.前言
1.在更改ref或reactive定义个响应数据时,是如何触发似的computed的值重新发生了变化呢
2.ref,reactive 和 computed的关联关系是怎么建立的呢
3.带着这两疑问,我们来解析下computed的实现过程
2.关系图
3.解析
1.ref与computed之间的关联关系说明
1.1.依赖收集
1.在vue实例化mount的过程中,会实例化一个 reactiveEffect实例,实例化会调用run方法,在run方法执行的过程中,会给activeEffect赋值
2.run方法实际就是编译后的render方法,所以render在渲染过程中,会去获取computed定义的变量值,在获取值的过程中,会触发trackRefvalue函数,在该函数内会判断activeEffect是否有值,有值的话就会调用trackEffect方法就行依赖收集
3.在mount实例化的reactiveEffect就相当于一个渲染依赖,或computed的属性值里,会将这个渲染依赖收集到computed的依赖中(此处完成了第一个依赖的收集)
4.获取computed的值时,会触发computed的get方法,在get方法内会判读单dirty是否为true,因为computed声明时dirty默认是为true的,dirty为true时会调用computed类下的effect.run方法,该run方法就是在使用computed时传染的自定义函数,在自定义函数中会有对应声明ref值的引用,所以获取ref值时,会触发ref的依赖收集,在执行computed.effect.run方法时,会把activeEffect赋值为computed的reactiveEffect依赖对象,所以在ref依赖收集时,收集的就是computed的reactitveEffect (此处完成了第二个依赖收集)
1.2.依赖更新
1.ref值更新时,会触发ref里的set方法,在set方法内,会触发triggerRefvalue方法,该方法会遍历ref.dep集合里收集的依赖,ref.dep里收集的就是computed的reactiveEffect, 所以依赖调用的run方法会执行computed的effect,在computed里默认初始化reactiveEffect时,会定义了一个scheduler方法,有了该方法时,triggerEeffect时将不会调用run,而是调用scheduler方法
4.调试代码
<div id="app">
<h1>{{message}}</h1>
<button @click="changeValue">click me</button>
</div>
<script>
const { createApp, ref, computed } = Vue
const msg = ref(10)
const message = computed(() => {
return msg.value + '-' + 'world!'
})
const baseVal = 10
createApp({
setup() {
const changeValue = () => {
msg.value += 10
console.log('message', message.value)
}
return {
message,
changeValue
}
}
}).mount("#app")
</script>