computed
一、认识
computed
侦听依赖的响应式数据, 根据传入类型, 生成不同的 Ref
类型的响应式数据。
-
computed(()=>{})
: 传入getter
函数, 返回一个只读的响应式ref
对象 -
computed({ get(){}, set(){} })
: 返回一个可读、可写的响应式ref
对象
二、语法
computed(()=>{},debuggerOptions?);
computed(
{
get(){
},
set(value){
}
},
debuggerOptions?:
);
三、用法
3.1 可读计算属性
import { ref, type Ref, computed } from 'vue'
const a: Ref<number> = ref(0)
const count = computed(() => {
return a.value * 10
})
3.2 可读可写计算属性
import { ref, type Ref, computed } from 'vue'
const a: Ref<number> = ref(0)
const count = computed({
get() {
return a.value * 10
},
set(value) {
a.value = value
}
})
3.3 收集、管理副作用
import { ref,stop,computed } from 'vue';
let disposables = [];
const count = ref(0);
const doubleCount = computed(()=> count.value * 2);
disposables.push(()=> stop(doubleCount));
setTimeout(()=>{
count.value++;
},2000);
setTimeout(()=>{
disposables.forEach(dispose=> dispose());
disposables = []
},4000);
setTimeout(()=>{
count.value++;
}, 60000);
四、对比
4.1 computed vs watch
watch
用于监测响应式数据, 当数据发生变化时, 通知并执行相应的回调函数。watch
传入的第一个参数为要监测的响应式数据, watch
中创建一个 effect
副作用, 第一个参数为封装好副作用函数, 这个副作用函数主要是读取传入的响应式数据, 触发响应式数据的副作用收集机制, 传入 Scheduler
配置项, 在 effect
中, 如果有 Scheduler
配置项, 那么执行 Scheduler
调度函数执行, 而不是直接触发副作用函数执行。在 Scheduler
调度函数中, 执行传入的 watch
回调。watch
有三个参数, 侦听器的源, 发生变化的回调, 和一个配置项, 可以配置 immediate
立即监听, 可以配置 deep
进行深度监听。 在变化的回调中, 同样提供了三个参数, 最新值, 旧值, 以及一个用于注册副作用清理的回调函数 cleanup
。 cleanup
可以用于解决一些竟态问题, 在响应式数据发生变化后, 调用 cleanup
, 并传入想要取消的逻辑代码, 优先取消之前的副作用影响后,再开始新的副作用。
computed
是一个计算属性, 根据传入的 getter
函数, 计算得到一个可读或者可读可写的响应式数据。 computed
本质上是将传入的 getter
作为一个副作用函数, 创建一个带有 lazy
和 scheduler
的 effect
, 返回一个具有访问器属性value
和 设置器属性value
的数据。在读取 computed
数据时, 访问器进行拦截, 在内部变量 dirty
为 true
的情况下, 执行通过 effect
返回的 effectFn
函数, 这个 effectFn
内部会执行 computed
传入的 getter
进行计算。因此, computed
同 ref
一样, 是一个新的状态数据, 并具有延时计算和缓存计算结果的功能。
4.2 computed vs methods
methods
: 多次访问 methods
中的方法, 总是多次执行;
computed
: computed
通过 dirty
控制是否重新计算、执行副作用函数, 通过 value
缓存计算结果。当且仅当其依赖的响应式数据发生变化, 触发 computed effect
的调度函数, 调度函数内部重新将 dirty
置为 true
, 再次访问的时候重新计算、执行副作用函数。