vue中数据劫持的底层实现原理

vue中数据劫持的底层实现原理

//Vue数据劫持代理
/*
首先,我们要搞清楚,数据劫持,劫持的是什么:data

*/

//模拟Vue里面的data选项
let data={
    //dada中是我们初始化数据的地方
    username:'zhousujuan',
    age:'21'
}
/*
初始化了两个数据:username、age
问题:
谁来劫持它们?(这两个初始化的数据)
this

*/

//模拟组件的实例
//实例上原本没有这个初始化的数据
//现在我们要去劫持代理上面的属性
//也就是说,我们最终的目标是;
//在this上面有这些属性
// let _this={
//     username:'zhousujuan',
//     age:'21'
// }
//但是底层上面的实现,不可能是直接粘贴复制---》而是要通过编码的形式去实现的
// 我们怎么去做尼?
/**
 * 1.可能有些认为,可以直接:_this.username=data.username;
 * 这不叫劫持代理,这叫做赋值
 * 而且,这样直接写的话,存在一个问题:
 * 我们修改_this.username这里的属性的时候,并不能监视到这个属性的变化
 * 所以并不是这个方法
 * 
 * 2.利用Object.defineProperty
 * 如何去实现尼?
 * 首先对data中的所有属性进行枚举,
 * 只有枚举出来,才能得到里面的key和对应的value
 * 进而才能想办法代理到我们的实例身上
 */
//这里因为this是一个关键字,所以我们这里用_this来展示
let _this={
    username:'zhousujuan',
    age:'21'
}

//错误方法
// _this.username=data.username;

//利用Object.defineProperty
//这个时候我们可以利用一个for循环
for(let item in data){
    //打印item和里面的value
    // console.log(item,data[item])
    /**
     * 查看后台打印,可以得到相应的值
     * 拿到之后,把里面的属性设置给this
     * 利用Object.defineProperty
     * 参数1:设置的目标对象:_this
     * 参数2:添加的属性(key):item
     * 参数3:对应的value应该是一个说明对象
     * 
     */
    Object.defineProperty(_this,item,{
        //这里面有很多种写法
        /**
         * 比如说,我们可以通过value去设置,但是这种没有get和set
         * 所以我们对应,应该用get和set写
         */
        get(){//用来获取扩展属性值的,当获取该属性值的时候调用get方法(也就是点击那三个点的时候)
            //get方法一定有一个返回值,这个返回值,其实就是当前扩展属性的value--->data[item]
            return data[item]
        },
        set(newValue){
            //监视扩展属性的,只要已修改就调用
            console.log('set()',newValue);
            //a打印出来了,说明set调用了,因为下面在进行修改
            //而且调用的时候,我们可以拿到最新的value值
            
            //既然外面不能进行修改,那么我们里面可不?
            // _this.username=newValue;
            /**
             * 这是一个死循环,
             * 为什么?
             * 因为set是一修改就会进行调用,
             * 首先,我们的外面进行修改--》调用set,
             * set里面又进行修改,又进行了调用,
             * 所以就进入了死循环
             * 并且我们没有结束的条件
             * ===》千万不要在我们的set方法中直接修改我们的扩展属性的值,会出现死循环
             * 
             * 在这里直接修改,有什莫用?
             * 在这里,它扮演的是监视
             * 我们想要修改_this身上的值,直接修改,修改不了,我们可以采取迂回战术
             * 注意:
             * _this身上对应的key叫什么,取决于谁?
             * 我们这里是把data上面的值,劫持到_this身上,所以我们可以通过修改data里面的值,
             * 修改:1.找到data对象
             */

            //1.找到data对象,注意我们要修改谁,当前的item
            //因为这是一个变量,对象操作变量的时候,我们需要需要中括号
            //当我们这样的话,整体的思路是:
            /**
             * 当我们修改_this的value的时候,调用set
             * 拿到我们最新的value赋值给data
             *把data中对应的属性进行修改
             因为data中的已修改
             又里面的扩展属性是依赖于人家的
             所以,_this里面的会跟着变化
             */
            data[item]=newValue;
        }

    })
}

//get写完之后,我们在进行一下打印
console.log(_this);
/**
 * 现在这个对象,不展开,什么属性都没有
 * 而我们展开看(因为扩展属性,需要我们展开之后,才能看得到)
 * 可以看到age、usrname
 * 而且我们看这两个属性,并不能直接看到它们的value
 * 显示的是age(...)
 * 我们需要点击一下,才能看到---》这个是典型的通过get得到的value值
 * 如果_this这个对象里面有个test:'测试',这样打印出来的就没有三个.,而是直接显示出来
 */

//除了get还有set
/**
 * 但是我们这里先进行,通过_this修改里面的属性
 * 不能修改成功,还是原来的值
 * 通过Object.defineProperty的get方法添加的扩展属性不能直接对象.属性,进行修改
 * 虽然不能直接修改,但是会触发set()方法
 */
_this.username='liliy';
//打印里面的username
console.log(_this.username);
//不能修改成功,还是原来的值
//通过Object.defineProperty的get方法添加的扩展属性不能直接对象.属性,进行修改

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值