胜负已分:Proxy VS Object.defineProperty

Object.defineProperty可以监听属性读写。Proxy是为对象设置访问代理器。

两者都可以用来设置监听,在vue2.0中使用Object.defineProperty进行数据监听,而在vue3.0中改用Proxy,两者有什么区别,又是什么原因促使vue作出如此变更呢?

一 Proxy使用

Proxy是一个类,通过new返回实例的方式来调用。

创建实例时它的构造函数接受两个参数,目标对象和监控对象,目标对象是要进行监控的对象,监控对象是用来配置监控行为的对象,可以设置get,set等属性。

1.1 get:访问操作

当访问proxy实例时,会访问监控对象的get,并传入两个参数,目标对象和访问的属性名。

const person = {
  name: 'kk',
  age: 23
}
const personProxy = new Proxy(person, {
  get(target, property){
    console.log(target, property) // { name: 'kk', age: 23 } name
    return 100
  },
  set(){}
})
console.log(personProxy.name) // 100

这里可以通过get对属性设置默认值。

const personProxy = new Proxy(person, {
  get(target, property){
    return property in target? target[property]: 'default'
  },
  set(){}
})
console.log(personProxy.name) // kk
console.log(personProxy.a) // default

如上,在通过get获取值时根据目标对象和访问属性,可以取到实际值,经过运算后将处理后的值return抛出,return的值就是调用实例中取到的值。

1.2 set:赋值操作

当写入proxy实例时,会访问监控对象中配置的set,并传入三个参数,为目标对象和访问的属性名,和写入值。

const personProxy = new Proxy(person, {
  ...
  set(target, property,value){
    console.log(target, property,value) // { name: 'kk', age: 23 } name 1
  }
})
personProxy.name = 1

可以在set中设置数据校验。

const personProxy = new Proxy(person, {
  ...
  set(target, property, value){
    if(property === 'age'){
      if(!Number.isInteger(value)){
        throw Error(value + 'is error')
      }
		}else {
        target[property] = value
    }
  }
})

二 Proxy优势

2.1 监控更加全面

除了get, set,proxy还有很多其他方法监控其他操作,如delete监控。

const personProxy = new Proxy(person, {
  ...
  deleteProperty(target, property){
      console.log(target, property)
  }
})

delete personProxy.age // { name: 'kk', age: 23 } age

2.2 支持数组监视

Object.defineProperty无法对数组进行监视,vue2.0通过重写数组操作方法的方式进行监视。

而proxy可以直接监视数组。

如下,对一个数组设置代理后,对代理运行的push、pop等方法都会转化为set和delete操作,反应在监控对象上。

const person = []
const listProxy = new Proxy(person, {
  set(target, property, value){
    console.log('set', target, property, value)
    target[property] = value
    return true // 设置成功
  },
  deleteProperty(target, property){
    console.log('del', target, property)
    return true
  }
})
listProxy.push(100)
//set [] 0 100
//set [ 100 ] length 1
listProxy.push(200)
//set [ 100 ] 1 200
//set [ 100, 200 ] length 2
listProxy.pop()
//del [ 100, 200 ] 1
//set [ 100, 200 ] length 1

2.3 非侵入式监视

proxy是非侵入的模式监视内部读写。不需要单独对属性设置。

指的一提的是,proxy仍然未实现深度监听,需要通过递归代理的方式监听。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值