【VUE】手写vue对数据监控原理

背景

  • 前面有篇文章写了个对所有对象增加get与set操作,这个只是在那基础上加几行代码。

代码


let arrayProto = Array.prototype//改写
let proto = Object.create(arrayProto)//相当于沿着这个对象__proto__可以找到Array上的方法。
;
['push','split','unshift'].forEach(method=>{//等等数组操作方法
    proto[method]=function(...args){
        console.log('更新');
        let tmp;
        switch(method){//为了拿到参数,把参数也代理。
            case'push':
            case 'unshift':tmp = args ;break
            case 'splice':tmp=args.slice(2);
            default : break;
        }
        observer(tmp)
        arrayProto[method].call(this,...args)
    }
})

function defineReactive(obj,key,value){
    if(typeof value === 'object'){
        observer(value)
    }
    Object.defineProperty(obj,key,{
        get(){
            return value
        },
        set(newVal){
            if(value!==newVal){
                if(typeof newVal=== 'object'){
                    observer(newVal)
                }
                console.log('更新');
                value =newVal
            }
        }
    })
}
function observer(obj){
    if(typeof obj  !== 'object' && obj ==='null'){
        return obj
    }
    if(Array.isArray(obj)){
        for(let i = 0 ;i<obj.length;i++){
            Object.setPrototypeOf(obj,proto)//相当于把Obj的__proto__改掉了
            observer(obj[i])
            
        }
    }else{
        for(let key  in  obj ){
            defineReactive(obj,key,obj[key]) 
        }
    }
}

//测试代码
// let data = {name : 'yehuo',age:11}
// observer(data)
// data.name={123:21,232:213}
// console.log(data.name[123]);
// let data = {123:{213:32}}
// observer(data)
// data[123][213]=5
// console.log(data[123][213]);

let data = [1,2,{3:22}]
observer(data)
// data[2][3]=500
// console.log(data[2][3]);     
data.push({23:123})
data[3][23]=111
console.log(data[3][23]);

思考

  • 这里面用的最绝的地方就是改写对象原来方法。
  • 首先,为什么要改写对象原来方法?因为需要监控传进来的参数,然后对这个参数进行代理,如果用原有方法是无法代理的。
  • 改写原理就是先让一个对象等于需要改写对象的原型,比如这里就是数组,要改数组上的方法。
  • 这样就得到一个有数组方法的对象,然后就新搞个对象把这个对象的__proto__指向它。
  • 最后改变obj的__proto__指向前面那个对象。
  • 这里改写的方法会加在proto对象上,而proto对象一开始是空的,这样obj去调用方法就会找proto对象上的,而arrayProto和Array.prototype是不能修改的,因为改一个就都改了。
  • 在改写方法里面再去调用真正的Array方法,同时代理新增元素。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

业火之理

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值