vue2与vue3的核心响应原理

vue2通过Object.defineProperty来实现双向绑定的。

代码如下:

<body>

    <input id="text"></input>
    
    <script>
        // js数据
        let obj = { jsText:'abc'};
        let tempVal;
        Object.defineProperty(obj,'jsText',{
            // 监视设置和
            set(newValue){
                console.log('jsText被改变了',newValue);
                // text.value = newValue;
                tempVal = newValue;
                // 更新页面的数据
                text.value = newValue;
            },
            get() {// 获取
                console.log('jsText被获取了');
                return tempVal;
            }
        });

        // 增加一个属性 无法察觉
        obj.a = '111';
        // 删除一个属性 无法察觉
        delete obj.a;
        
        text.oninput = function(e) { // 用户输入改变js内存
           obj.jsText = e.target.value;
        }
    </script>


</body>

由于vue2不能察觉动态的添加和删除属性。只能通过$set去添加。$delete去删除。而vue3这次则做了升级。

vue3则是用ES6 Proxy 对象的属性及各种操作进行监控,支持添加以及删除

<body>
    <script>
        let obj = {  text:'abc'};
        
        // ES6 Proxy 对象的属性及各种操作进行监控
        let proxy = new Proxy(obj,{
            set(target,propKey,value){
                target[propKey] = value;
                console.log('set||add:',arguments);
                return true;
            },
            get(target,propKey){
                console.log('get:',arguments);
                return target[propKey];
            },
            deleteProperty(target,propName) {
                console.log('删除了')
            }
        });

        // vue2不能察觉动态添加和删除属性
        proxy.abc = '123';
        delete proxy.abc;
        
    </script>
</body>

proxy的api

 

<script>
        
        let obj = {a:'xxx'};
        let p = new Proxy(obj, {
            get(target, propKey, receiver) {
                console.log('get')
                return Reflect.get(target, propKey)

            },
            set(target, propKey, value, receiver) {
                console.log('set')
                return Reflect.set(target, propKey, value)

            },
            has(target, propKey) {
                console.log('has')
                return Reflect.has(target, propKey)

            },
            deleteProperty(target, propKey) {
                console.log('deleteProperty')
                return Reflect.deleteProperty(target, propKey)

            },
            ownKeys(target) {
                console.log('ownKeys')
                return Reflect.ownKeys(target)

            },
            getOwnPropertyDescriptor(target, propKey) {
                console.log('getOwnPropertyDescriptor')
                return Reflect.getOwnPropertyDescriptor(target, propKey)

            },
            defineProperty(target, propKey, propDesc) {
                console.log('defineProperty')
                return Reflect.defineProperty(target, propKey, propDesc)

            },
            preventExtensions(target) {
                console.log('preventExtensions')
                return Reflect.preventExtensions(target)

            },
            getPrototypeOf(target) {// 不同
                console.log('getPrototypeOf')
                return Reflect.getPrototypeOf(target)

            },
            isExtensible(target) {
                console.log('isExtensible')
                return Reflect.isExtensible(target)

            },
            setPrototypeOf(target, proto) {
                console.log('setPrototypeOf')
                return Reflect.setPrototypeOf(target, proto)

            },
            
        });

        // // ====
        p.a;
        p.plus = '附加属性';
        'a' in p;
        delete p.plus;
        Object.getOwnPropertyNames(p)
        Object.getOwnPropertyDescriptor(p, 'a')
        Object.defineProperty(p,'c',{
            value:'ccc'
        });
        Object.getPrototypeOf(p)
        Object.isExtensible(p)
        Object.setPrototypeOf(p,{})
        Object.preventExtensions(p); // 放最后, 不然97上面无法设置
        
        console.log('下方是函数的操作')
        let Person = function(){
            console.log('1111');
        }
        
        let proxyFn = new Proxy(Person,{
            apply(target, object, args) {
                console.log('apply')
                return Reflect.apply(target, object, args)

            },
            construct(target, args) {
                console.log('construct')
                return Reflect.construct(target, args)

            },
        });
        proxyFn.call({});  
        // bind没有 因为bind是返回一个新函数,
        // 把新函数进行proxy
        new proxyFn();
    </script>

proxy和defineProperty对比

  •  proxy还能够检测到更多对象相关的操作,比如构造函数被调用
  • 在nodejs x个版本下, 执行多次defineProperty 和proxy,proxy慢了30倍
  • 为了继续使用响应式,在vue2.x中额外增加和删除的属性需要使用 Vue.set(对象,添加的key,添加值)
  • 【虽然单个API有性能差距,但是到Vue3中,可以利用Proxy带来的便利,在其他方面大幅提升性能】
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值