打开一直在写的案例
然后 找到src下的 dataResp.js
这里 我们Observer中 数数组和对象还是要分开处理 因为他们还是有所不同
我们修改 Observer 类代码如下
class Observer{
constructor(value) {
//相当于 给拿到的对象 其中的__ob__绑定 值为thsi,在类中用this 表示取实例本身给__ob__赋值 最后一个enumerable为false 表示属性不参与for遍历
def(value,'__ob__',this,false);
if(Array.isArray(value)){
Object.setPrototypeOf(value, arrayMethods);
this.observeArray(value);
}else{
this.walk(value);
}
}
walk(value) {
for(let key in value){
defineReactive(value,key);
}
}
observeArray(arr) {
for(let i = 0;i < arr.length;i++) {
observe(arr[i]);
}
}
}
这里 我们判断到数组时 会去调用observeArray 传递的参数value就是数组本身
然后 我们observeArray 拿到数组 也就是 将他变量 重新去调用observe 保证每一个下标都继续去递归处理响应式
然后 我们看到 Arrays.js 数组的方法中有几个比较特殊的存在
push unshift splice 他们都会在特殊位置插入一些数据
我们将 Arrays.js 代码更改如下
import { def } from './def.js';
const arrayPrototype = Array.prototype;
export const arrayMethods = Object.create(arrayPrototype);
const redefineArrayMethod = [
'push',
'pop',
'shift',
'unshift',
'splice',
'sort',
'reverse'
]
redefineArrayMethod.forEach(item =>{
const backupFunction = arrayPrototype[item];
def(arrayMethods,item,function(){
const result = backupFunction.apply(this, arguments);
const ob = this.__ob__;
const args = [...arguments];
let inserted = [];
switch (item) {
case "push":
case "unshift":
inserted = args;
break;
case "splice":
inserted = args.slice(2);
break;
}
if(inserted){
ob.observeArray(inserted);
}
console.log('数组执行了',item,'操作,值被修改为',this);
return result;
},false);
})
重点是 redefineArrayMethod.forEach 中 def第三参数中函数的变化
我们先拿到数字的__ob__字段 这里 我们说过 __ob__存的是Observer声明出来的类对象
然后 用args储存方法访问的参数 例如 push 我们这里 就是存push中的内容将push中的参数 转成一个数组 存给args
然后我们定义了一个 inserted 主要就是记录一下 有没有插入的下标
然后我们通过switch 确定方法的类型 如果是push unshift 那么参数肯定是都要用来添加到数组中的 直接等于 用inserted去存就好了
但splice第二个参数 才是要插入的值
如果是空的就算了
然后 我们将新插入的下标也扔给了__ob__类对象中的observeArray让新下标也带有响应式
那么 写完了 我们要如何测试有没有效果呢?
我们来到output.js 改写代码如下
import { observe } from "./dataResp"
const output = () => {
var obj = {
data: {
data: {
map: {
dom: {
isgin: true
}
},
arg: 13
},
name: "小猫猫"
},
bool: [1,2,3,4]
};
observe(obj);
obj.bool.splice(2,1,[88,99]);
document.getElementById("text").innerHTML = obj.data.name;
}
export default output
这里 我们通过splice 指定对 2下标出手 去除一条数据 插入新的数据 [88,99]
运行结果如下
可以看到 不但数据插入成功 且被监听了事件 我们新插入的数组 受我们新写的递归作用 也被加上了响应式 重下面的 ob 就能看出来