梗概
原理
从 3.4 开始,计算属性仅在其计算值较前一个值发生更改时才会触发副作用。
例如,以下 isEven 计算属性仅在返回值从 true 更改为 false 时才会触发副作用,反之亦然:
const count = ref(0)
const isEven = computed(() => count.value % 2 === 0)
watchEffect(() => console.log(isEven.value)) // true
// 这将不会触发新的输出,因为计算属性的值依然为 `true`
count.value = 2
count.value = 4这减少了非必要副作用的触发。但不幸的是,如果计算属性在每次计算时都创建一个新对象,则不起作用:
const computedObj = computed(() => {
return {
isEven: count.value % 2 === 0
}
})由于每次都会创建一个新对象,因此从技术上讲,新旧值始终不同。即使 isEven 属性保持不变,Vue 也无法知道,除非它对旧值和新值进行深度比较。这种比较可能代价高昂,并不值得。
相反,我们可以通过手动比较新旧值来优化。如果我们知道没有变化,则有条件地返回旧值:
const computedObj = computed((oldValue) => {
const newValue = {
isEven: count.value % 2 === 0
}
if (oldValue && oldValue.isEven === newValue.isEven) {
return oldValue
}
return newValue
})