最近重看 vue 官网,好奇所谓的计算属性是怎么的一回事。官网是这样说的:
计算属性是基于它的依赖缓存。计算属性只有在它的相关依赖发生改变时才会重新取值。这就意味着只要 message 没有发生改变,多次访问 reversedMessage 计算属性会立即返回之前的计算结果,而不必再次执行函数。
另外,依赖必须是响应式依赖,所以若计算属性绑定 Date.now()
的话是不会更新的了。
这个在计算复杂比较大的时候是比较有用的,如排序数组然后得到结果。用 methods 的话,每次重新渲染,不管依赖有没有修改,都会重新计算一次,造成较大的浪费。
那为什么一定是响应式依赖呢。为什么计算属性会知道它的依赖是什么呢。对vue的响应式原理了解的人应该能想到大概原理,应该是在getter与setter中里加了逻辑。
大概原理是这样:
-
响应式依赖中加逻辑。
-
初始化计算属性的值,此时会触发对应依赖的getter,新增的逻辑会记录下来计算方法。
-
下次有依赖属性改变时,会在setter中循环记录下来的计算方法,更新计算属性的缓存值。
简单实现逻辑
let data = {
a: 3
}
let comp = {
b: function () {
return data.a * 24 + 3
}
}
let computedFn = null;
function defineReactive(obj, key, val) {
let deps = [];
Object.defineProperty(obj, key, {
get() {
if (computedFn) {
deps.push(computedFn);
}
return val;
},
set(newVal) {
val = newVal;
deps.forEach(_ => _());
}
})
}
function defineCompute(obj, key, computed) {
let val;
const fn = function () {
val = computed();
}
computedFn = fn;
computedFn();
computedFn = null;
Object.defineProperty(obj, key, {
get() {
return val;
}
})
}
defineReactive(data, 'a', data.a);
defineCompute(comp, 'b', comp.b);
console.log(b) // 75
data.a = 1;
console.log(b) // 27
这个就实现了,其实还是应用了setter 与 getter的钩子
网友评论