回忆
在上一篇Vue响应式原理-理解Observer、Dep、Watcher简单讲解了Observer
、Dep
、Watcher
三者的关系。
在Observer
的伪代码中我们模拟了如下代码:
class Observer {
constructor() {
// 响应式绑定数据通过方法
observe(this.data);
}
}
export function observe (data) {
const keys = Object.keys(data);
for (let i = 0; i < keys.length; i++) {
// 将data中我们定义的每个属性进行响应式绑定
defineReactive(obj, keys[i]);
}
}
export function defineReactive () {
// ...省略 Object.defineProperty get-set
}
复制代码
今天我们就进一步了解Observer
里还做了什么事。
Array的变化如何监听?
data
中的数据如果是一个数组怎么办?我们发现Object.defineProperty
对数组进行响应式化是有缺陷的。
虽然我们可以监听到索引的改变。
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("数据被改变了,我要渲染到页面上去!");
}
})
}
let data = [1];
// 对数组key进行监听
defineReactive(data, 0, 1);
console.log(data[0]); // 我被读了,我要不要做点什么好?
data[0] = 2; // 数据被改变了,我要渲染到页面上去!
复制代码
但是defineProperty
不能检测到数组长度的变化,准确的说是通过改变length而增加的长度不能监测到。这种情况无法触发任何改变。
data.length = 0; // 控制台没有任