let proto = Object.create(arrayProtos); //创建新的对象
['push', 'shfit', 'splice'].forEach(method => {
proto[method] = function (...args) { //这个数组应该也被监控
// console.log(arguments)
let inserted; //默认没有插入新的数据
switch (method) {
case 'push':
case 'unshift':
inserted = args
break;
case 'splice': //数组splice只有传递三个参数,才有追加效果
inserted = args.slice(2);
default:
break;
}
console.log('视图更新2')
ArrayObserver(inserted)
arrayProtos[method].call(this, ...args)
}
});
//监控数组
function ArrayObserver(obj) {
for (let i = 0; i < obj.length; i++) {
let item = obj[i];
//如果是普通值就不监控
observer(item); //如果是对象会被defineReactive
}
}
function observer(obj) {
if (typeof obj !== 'object' || obj == null) {
return obj;
}
if (Array.isArray(obj)) {
//上面处理的是数组格式 push shift splice(如果调用这三个方法,应该把这个值判断以下是否是对象)
// obj._proto_ = proto;
Object.setPrototypeOf(obj, proto); //实现一个对数组的方法的重写
// console.log(obj)
ArrayObserver(obj)
// for (let i = 0; i < obj.length; i++) {
// let item = obj[i];
// observer(item); //如果是对象会被defineReactive
// }
} else {
//下面是处理对象的
for (let key in obj) {
defineReactive(obj, key, obj[key]);
}
}
}
function defineReactive(obj, key, value) {
//默认只循环第一层
observer(value); //递归创建响应式数据,但是会导致性能不好
Object.defineProperty(obj, key, {
get() {
return value;
},
set(newValue) { //给某个key设置值的时候,可能也是一个对象
if (value !== newValue) {
observer(newValue)
value = newValue
console.log('试图更新')
}
}
})
}
let data = {
d: [1, 2, 3, {
name: 'ccp'
}]
};
observer(data);
data.d[3].name = 'cypjiayou'
data.d.push({
name: 'ff'
})
// console.log(data.d[4])
// console.log(data.name)
//data.name = '123'; //vue缺点:1.增加不存在的的属性,不能更新视图。走set(vm.$set可以)
//data.name.n = '123' //2.vue默认会递归所有增加getter和setter
// data.name = {
// n: 'js'
// }
// data.name = '123';
//vue特点:使用对象的时候,必须先申明属性,这个属性才是响应式的\
//3.数组里套对象 对象是支持响应式变化的,如果是常量则没有效果
//4.修改数组索引长度是不会导致视图更新的
//5.如果新增的数据,vue中也会帮你监控(对象类型)```