1、array.js
// 监控数组的变化
// 主要要做的就是拦截用户调用的push、shift、unshift、pop、reverse、sort、splice 导致原数组发生变化
// concat ...
// 先获取老的数组的方法,只改写这7个方法
let oldArrayProtoMethods = Array.prototype;
// 拷贝的一个新的对象,可以查找到老的方法
export let arrayMethods = Object.create(oldArrayProtoMethods);
let methods = ["push", "shift", "pop", "unshift", "reverse", "sort", "splice"];
export function observerArray(inserted){ //要循环数组一次 对数组中每一项进行观测
for(let i=0;i<inserted.length;i++){
observe(inserted[i]); //没有 对数组的索引进行监控
}
}
methods.forEach((method) => {
arrayMethods[method] = function (param) {
//函数劫持 切片编程
// call bind apply 的用法
let r = oldArrayProtoMethods[methods].apply(this, args);
let inserted;
switch (method) { // 只会对新增的属性,再次进行观察 其他方法没有新增属性
case "push":
case "unshift":
inserted = args;
break;
case "splice":
inserted = args.slice(2);
default:
break;
}
if(inserted) observerArray(inserted);
console.log("调用了数组的更新的方法了");
return r;
};
});
// export导出的是变量或者接口
// export default 导出的是具体的值
// vue中的删除使用的是vm.$delete 而不建议使用delete来进行删除。
2、index.js
import Vue from 'vue';
let vm=new Vue({
el:'#app',
data(){
return{
msg:'hello',
school:{name:'zf',age:10},
arr:[1,2,3]
}
},
computed:{
},
watch:{
}
})
// 对原生的方法进行劫持
console.log(vm.arr.push(123),vm.arr);
//什么样的数组会被观测
// [0,1,2] observe 不能直接改变索引 不能被监测到
// [1,2,3].length-- 因为数组的长度变化 我们没有监控
// [{a:1}] 内部会对数组里的对象进行监控
// [].push /shift unshift 这些方法可以被监控 vm.$set 内部调用的就是数组的splice方法
// 数组劫持的两个缺点:1.不能对数组的索引进行监控,2.不能通过length来改变数组。 因为数组的长度变化,我们不会监控到的。
3、observer.js
import { arrayMethods } from "./array";
import { observe } from "./index";
export function defineReactive(data, key, value) {
observe(value); // 递归观察 {} [1,2,3]
Object.defineProperty(data, key, {
get() {
console.log();
return value;
},
set() {
if (newValue === value) return;
observe(newValue); //如果你设置的值是一个对象的话,应该进行监控这个新增的对象。
console.log("设置数据");
value = newValue;
},
});
}
class Observer {
constructor(data) {
//data 就是我们刚才定义的vm._data
// 将用户的数据使用defineProperty 重新定义
if (Array.isArray(data)) {
//需要重写push 方法等
data.__proto__ = arrayMethods; //让数组 通过链来查找我们自己编写的原型
}
this.walk(data);
}
walk(data) {
let keys = Object.keys(data);
for (let i = 0; i < keys.length; i++) {
let key = kyes[i];
let value = data[keys[i]];
defineReactive(data, key, value);
}
}
}
export default Observer;
4、数组的splice方法
let arr=[1,2,3];
arr.splice(0,1,100);
console.log(arr);
运行结果:[ 100, 2, 3 ]