ref
无论在结构
还是使用上都和computed
几乎一致,ref
主要是为了给原始类型(premitive type)
设置响应式,而computed
是计算属性
,为的是代替在模板
中直接使用函数
,并且提供了缓存机制
,以及提供了响应式
。实际上这两个函数
都有两个共同的属性—-value
和dep
。
value
没什么要说的,就是值
,这里重点提一下dep
,实际上dep
存储的是ref
或者computed
当前的ReactiveEffect
:
当然首先要了解什么是ReactiveEffect
,实际上这是副作用
的一层包装
,我们可以通过几个重要的属性
来了解它:
- fn:执行这个函数时,会执行
track
,把ReactiveEffect
添加到dep
上 - scheduler:这个是
副作用函数
,上图中就是componentUpdateFn
,实际上被模板引用
都会有这个函数
,就是更新dom
- onTrack:
调试
用的钩子,在追踪依赖
时触发,实际上在computed
第二个参数有相同
名称的选项,computed
传递了onTrack参数
之后,这里会出现相同的引用:
- onTrigger:
调试
用钩子,依赖
被触发
时调用,其它和onTrack
一样 - run:实际上
vue
维护了一个ReactiveEffect
栈,来处理嵌套
的副作用
,所以这个函数
实际上是用来处理副作用
,并调用fn
,然后返回fn
的返回值
。
当然还有一个知识点
要了解,就是trigger
,track
,这两个是响应式
系统的核心,track
是追踪函数
,创建对应的ReactiveEffect
,在读
操作的时候执行。trigger
是触发函数,执行对应的ReactiveEffect
函数,在写
的时候执行。
然后抛出几个问题,来理解ref
和computed
的关系
- 为什么
computed
中书写的ref
值改变时,会触发computed
对应的副作用
?
<script setup>
import { ref, watch,computed } from 'vue';
const a = ref(1)
const b = computed(() => a.value)
watch(b,()=>{
console.log(b.value)
})
a.value++
</script>
实际上,computed
的源码中,让ref
的值,主动添加了对当前effect
的引用:
所以,ref
改变时,就触发了triggerRefValue
来执行computed
的deps
2.当computed
只有getter
时,为什么computed(()=> Data.now())
永远不会变?
实际上computed
上还有一个非常重要的属性_dirty
,这个属性
是用来判断当前值是否发生变化
的,是做缓存
用的。如果是false
的话,则永远不会重新执行run
,也就不会拿到新值
但是ref
值变化时会更新_dirty
:
所以ref
值会刷新computed
的_dirty
属性,并执行computted
的副作用
原文链接:https://juejin.cn/post/7258337246024187959 作者:RadiumAg
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。