之前写过一篇响应式原理-如何监听Array的变化,最近准备给团队同事分享,发现之前看的太粗糙了,因此决定再写一篇详细版~
一、如何监听数组索引的变化?
(1)案例分析
相信初学Vue的同学一定踩过这个坑,改变数组的索引,没有触发视图更新。 比如下面这个案例:
var vm = new Vue({
data: {
items: ['a', 'b', 'c']
}
})
vm.items[1] = 'x' // 不是响应性的
(2)解决方式
Vue官方文档也有给出,使用Vue.set即可达到触发视图更新的效果。
// Vue.set
Vue.set(vm.items, indexOfItem, newValue);
(3)Vue为何不能监听索引的变化?
Vue官方给出了解释,不能检测。
由于 JavaScript 的限制,Vue 不能检测以下数组的变动: 当你利用索引直接设置一个数组项时,例如:vm.items[indexOfItem] = newValue。
那原因是什么?我在学习的过程中发现很多文章都在断章取义,Vue官方给出了解释是【Vue不能检测】,而很多文章写出的是【Object.defineProperty不能检测】。
但实际上Object.defineProperty是可以检测到数组索引的变化的。如下案例:
let data = [1, 2];
function defineReactive (obj, key, val) {
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: () => {
console.log('我被读了,我要不要做点什么好?');
return val;
},
set: newVal => {
if (val === newVal) {
return;
}
val = newVal;
console.log("数据被改变了,我要渲染到页面上去!");
}
})
}
defineReactive(data, 0, 1);
console.log(data[0]);
data[0] &