Vue3为什么要用Proxy替代defineProperty

34 篇文章 1 订阅
10 篇文章 0 订阅

Vue3为什么要用Proxy替代defineProperty

先导知识:Object.defineProperty()和Proxy

Object.defineProperty()
// Object.defineProperty() 方法直接在一个对象上定义一个新属性,或者修改一个已经存在的属性, 并返回这个对象
Object.defineProperty(obj, prop, descriptor)
// obj 需要定义属性的对象。
// prop 需被定义或修改的属性名。
// descriptor 需被定义或修改的属性的描述符,Object类型

// 添加属性,允许添加任何类型
var user = {};
Object.defineProperty(user,"name",{
	value:"mkbird",
    // 设置允许被修改,默认为false
    writable:true
})
Object.defineProperty(user,"isSlow",{
	value:true
})
Object.defineProperty(user,"sayHi",{
	value:function () { console.log("Hi !") }
})
Object.defineProperty(user,"age",{
	value:18
})

descriptor下有几个属性

  • writable是否允许被修改,默认为false,不允许
  • enumerable属性是否可以被枚举,默认为false,支持
  • configurable是否属性可以被删除和重新定义特性,默认false不允许
  • get,获取值的时候的方法,类型为 function ,获取值的时候会被调用,不设置时为 undefined
  • set,设置值的时候的方法,类型为 function ,设置值的时候会被调用,undefined

当使用了getter或setter方法,不允许使用writable和value这两个属性

Proxy

Proxy为JS中的代理,用来实现对代理对象的拦截和自定义

相当于在外界访问对象前,要先经过代理的处理

// target为要代理的对象
// handler为操作
const p = new Proxy(target, handler)

handler有下列几个属性

  • get(target, propKey, receiver):拦截某个属性的读取操作
    • target为目标对象
    • propKey为属性
    • receiverproxy 实例本身(可选)
    var p = new Proxy(user,{
      get:function(target,property,receiver){
        if(property === 'name'){
          console.log('name被读取');
        }
      }
    })
    
    p.name// name被读取
  • set(target, propKey, value,receiver)
    • value为属性值,其他和上面一样
    var p = new Proxy(user,{
      get:function(target,property,receiver){
        if(property === 'name'){
          console.log('name被读取');
        }
      },
      set:function(target,property,value,receiver){
        console.log('set监控到对象中有属性被修改');
        console.log(property,value);
          // name ls
      }
      
    })

    p.name='ls'// set监控到对象中有属性被修改
// 注意,p作为代理被修改,并不会改变原来对象的属性值
Object.defineProperty与Proxy区别
  • Proxy监听对象;Object.defineProperty监听具体属性
  • Proxy可以监听数组的变化,拦截方法也多
  • Proxy返回的是一个新对象,我们只能操作这个新对象,不会影响旧对象的属性;Object.defineProperty直接影响
ES5中,通过defineProperty()的set进行监听
    user={
      name:'zs',
      age:12
    }
    // 通过defineProperty()进行监听
    Object.defineProperty(user,'name',{
      set:function(){
        console.log('name改变');
      }
    })
    user.name='ls'
// name改变
ES6中,通过Proxy实现
    var user = new Proxy({},{
      set(target,key,value){
        
      }
    })

为什么要替代替代

defineProperty只能对单例属性做监听

Vue2中基于defineProperty中的descriptor,对data中的属性做了遍历+递归,为每个属性设置了getter和setter

所以Vue2中只能对data中预定义过的属性错处响应,在Vue2中使用下标的方式直接修改一个值或者添加一个预先不存在的对象属性无法做到setter监听

Proxy代理对象

Proxy监听是针对一个对象,这个对象的所有操作都会进入监听,这样可以完全代理所有属性,带来很大的性能提升和代码优化

响应式是懒惰的

Vue2中,对于一个深层嵌套的对象,要劫持它内部的变化,需要递归遍历这个对象

Vue3中,Proxy并不能监听到深层属性的变化,它的处理方式是在getter中递归响应,真正做到了谁变换,谁响应

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

会飞的战斗鸡

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

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

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

打赏作者

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

抵扣说明:

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

余额充值