1 - Proxy
const o = { a: 1 }
const proxy = new Proxy(o, {
get(target, key, receiver) {
console.info('get')
// return target[key]
return Reflect.get(target, key, receiver)
},
set(target, key, value, receiver) {
console.info('set')
target[key] = value
// return true // set 最后需要 return true 表示赋值成功,否则会报错
return Reflect.set(target, key, value, receiver)
}
})
proxy.b = 2 // proxy 可以监听到新增的属性
2 - Object.defineProperty
const o = { a: 1 }
const defineReactive = (target, key, midValue, configurable = true, enumerable = true) => {
Object.defineProperty(o, 'a', {
configurable,
enumerable,
get() {
console.info('get:' + midValue)
return midValue
},
set(value) {
console.info('set:' + value)
midValue = value
}
})
}
defineReactive(o, 'a', o['a'])
3 - proxy 和 defineProperty 的区别
1、proxy 代理的 set 方法中需要 return true,否则会报错
2、defineProperty 会拦截原对象,只需访问或修改 原对象 即可触发get、set方法。
proxy会对原对象进行代理,需要访问或改变 代理后的对象 才能触发get、set等方法
3、defineProperty 的 get 方法没有参数,需要一个中间值(midValue)去记录 set 方法触发时改变后的新值
proxy 由于监听的是对象, get 方法有参数 target、key(set也有),可以直接获取到访问的值,并return出去
4、proxy 除了 get 和 set ,还有其他拦截方法,比如监听数组,监听对象属性的新增,删除等,共13种。
5、当对象上新增属性时,proxy 可以监听到对象新增的属性。
defineProperty 无法监听到新增的属性,需要手动监听(Vue2.x 中的 $set 方法,在 3.0 中废除掉了 )
4 - Vue3.0 使用 Proxy 的优势
① 在 Vue2.x 中,对象上新增的属性不会触发视图更新,因为Object.defineProperty 无法监听到新增的属性,需要使用 Vue 提供的 $set 方法手动拦截监听(会通过Object.defineProperty将该属性进行拦截监听)
<div>{{ obj }}</div>
export default {
data() {
return {
obj: {
name: 'xhl'
}
}
},
mounted() {
// this.obj.age = 24 // 不会更新视图
this.$set(this.obj, 'age', 24) // √
},
}
在 Vue3.0 中废除了 $set 方法,因为 Proxy 可以监听到对象上新增的属性