Vue源码响应式小结:注意事项

242 阅读1分钟

响应式注意事项

从源码了解了响应式的基础,我们应该明白在业务上注意什么?

不要赋值新对象

观察下列示例

const a = {
    a: 1,
    b: {
        c: 2
    }
};
new Oberserve(a);
a.b = {
    c:2
}
function log(thisValue:unknown,oldValue:unknown){
    return console.log(`new:${thisValue},old:${oldValue}`);
}
new Watcher(a,"b.c",log)
a.b.c = 3;

会打印吗?显然不会,重新赋值对象已经失去了响应式了。

不要新增或删除对象上的键

Object.defineProperty方法实现了观察对象上的键,它是遍历对象的键并转换为响应式,无法监测后续对象上键的改变。

所以,向object数据里添加一对新的key/value或删除一对已有的key/value时,它是无法观测到的 。此处不再举例。

不要索引数组改变其值

Vue中数组内的值的改变是没有响应式的。

const a = {
    b: [1,2,3,4]
};
new Oberserve(a);
function log(thisValue:unknown,oldValue:unknown){
    return console.log(`new:${thisValue},old:${oldValue}`);
}
new Watcher(a,function(){ return this.b[0] },log)
a.b[0] = 10;
//并不能响应

只能通过数组方法push,slice,unshift来响应。

这三个问题,Vue都注意到了,如果你有需求,可以Vue.set和Vue.delete保证响应式。

在Vue3中,响应式部分已经被Proxy重写,它可以监测到一个对象键的改变和数组的索引值改变,不存在上述问题。

不要在computed中对数据改动

考虑以下示例

new Watcher(a,function(this:typeof a,vm){
    this.a++;
    return this.a + this.e
},log)
//RangeError: Maximum call stack size exceeded

这会导致无限进入getter函数而爆栈