computed面试题
# computed面试题
面试题:谈谈 computed 的机制,缓存了什么?为什么 computed 不支持异步?
响应式系统:
- track:进行依赖收集,建立数据和函数的映射关系
- trigger:触发更新,重新执行数据所映射的所有函数
computed开发者使用:
const state = reactive({
a: 1,
b: 2
})
const sum = computed(() => {
return state.a + state.b
})
const firstName = ref('John')
const lastName = ref('Doe')
const fullName = computed({
get() {
return firstName.value + ' ' + lastName.value
},
set(newValue) {
;[firstName.value, lastName.value] = newValue.split(' ')
}
})
computed核心实现:
- 参数归一化,统一成对象的形式
- 返回一个存取器对象
import { effect } from "./effect/effect.js";
import track from "./effect/track.js";
import trigger from "./effect/trigger.js";
import { TriggerOpTypes, TrackOpTypes } from "./utils.js";
// 参数归一化
function normalizeParameter(getterOrOptions) {
// 代码略
}
/**
*
* @param {*} getterOrOptions 可能是函数,也可能是对象
*/
export function computed(getterOrOptions) {
// 1. 参数归一化
const {getter, setter} = normalizeParameter(getterOrOptions);
// value 用于存储计算结果, dirty 负责控制从缓存中获取值还是重新计算新的值,dirty为true就代表要重新计算
let value, dirty = true;
// 让getter内部的响应式数据和getter建立映射关系
// 回头getter内部的响应式数据发生变化后,重新执行getter
const effectFn = effect(getter, {
lazy: true,
scheduler(){
dirty = true;
trigger(obj, TriggerOpTypes.SET, "value")
}
})
// 2. 返回一个存取器对象
const obj = {
get value(){
// 需要将 value 和渲染函数建立映射关系
track(obj, TrackOpTypes.GET, "value")
if(dirty){
value = effectFn()
dirty = false;
}
return value;
},
set value(newValue){
setter(newValue)
}
}
return obj;
}
面试题:谈谈 computed 的机制,缓存了什么?为什么 computed 不支持异步?
参考答案:
谈谈 computed 的机制,缓存了什么?
缓存的是上一次 getter 计算出来的值。
为什么 computed 不支持异步?
computed 属性在 Vue 中不支持异步操作的主要原因是设计上的理念和使用场景的考虑。computed 属性的初衷是用于计算并缓存一个基于响应式依赖的同步计算结果,当其依赖的响应式数据发生变化时,Vue 会自动重新计算 computed 的值,并将其缓存,以提高性能。
computed 不支持异步的几个具体原因:
- 缓存机制与同步计算:computed 属性的一个核心特性是缓存。当依赖的响应式数据没有变化时,computed 的计算结果会被缓存并直接返回,而不会重新执行计算。这种缓存机制是基于同步计算的,假如允许异步计算,那么在异步操作完成之前,computed 属性无法提供有效的返回值,这与它的同步缓存理念相违背。
- 数据一致性:computed 属性通常用于模板中的绑定,它的计算结果需要在渲染期间是稳定且可用的。如果 computed 支持异步操作,渲染过程中的数据可能不一致,会导致模板渲染时无法确定使用什么数据,从而可能造成视图的闪烁或数据错误。
- 调试与依赖追踪困难:如果 computed 属性是异步的,那么在调试和依赖追踪时就会变得非常复杂。异步操作的完成时间不确定,会使得依赖追踪的过程变得不直观,也难以预期。
如果需要进行异步操作,通常推荐使用 watch 来实现。
-EOF-