返回
Vue 数组响应性更新的深入探索:方法、局限和底层实现
前端
2023-09-17 23:34:31
Vue.js 数组响应性更新:方法、不支持情况和底层实现
支持响应性更新的方法
Vue.js 提供了多种数组变异方法,可触发响应性更新:
push()
pop()
shift()
unshift()
splice()
sort()
reverse()
这些方法被 Vue.js 内部包裹,当它们被调用时,会触发 notify()
方法,从而更新视图。
不支持的情况
如果使用非变异方法修改数组,例如直接将数组元素重新赋值给新值,则不会触发响应性更新。在这种情况下,需要手动使用 Vue.set()
方法更新数组元素:
// 会触发响应性更新
example1.items.push({ message: 'Foo' });
// 不会触发响应性更新
example1.items[0].message = 'Bar';
// 手动触发响应性更新
Vue.set(example1.items, 0, { message: 'Bar' });
底层实现
Vue.js 通过 Object.defineProperty()
将响应性注入数组。当创建新数组时,Vue.js 会使用 Object.defineProperty()
为数组的 length
和每个索引属性添加 getters 和 setters。这些 getters 和 setters 负责在更改数组时触发 notify()
方法。
具体来说,Vue.js 为每个数组索引属性定义了如下 getter 和 setter:
Object.defineProperty(arr, index, {
get: function() {
return this._data[index];
},
set: function(val) {
this._data[index] = val;
notify();
}
});
类似地,Vue.js 还为数组的 length
属性定义了 getter 和 setter:
Object.defineProperty(arr, 'length', {
get: function() {
return this._data.length;
},
set: function(val) {
this._data.length = val;
notify();
}
});
当使用支持的变异方法修改数组时,Vue.js 会直接调用数组索引属性或 length
属性的 setter。这会触发相应的 getter,从而调用 notify()
方法并更新视图。