vue2数据响应式原理(6) 处理数组特殊遍历

打开一直在写的案例
然后 找到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 就能看出来

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值