这是我参与11月更文挑战的第19天,活动详情查看:2021最后一次更文挑战
一、Proxy取代defineProperty
先说说es6中的proxy:
let obj = new Proxy(target,handler);
这个里面的Proxy有两个对象:
- target: 被代理对象
- handler:是一个对象,声明代理target的某些操作
- obj是被代理对象完成后返回的对象
Vue3中使用proxy提高了性能,打包后代码量也减少了很多,并且取代了Vue2中的definePeoperty的一些缺陷:属性的新增和删除无法实时监听,数组元素的新增和删除也无法监听。并且可以支持Map,set等,这就是Proxy增加了delete的原因。
reactive
function reactive(target) {
const handlers = collectionTypes.has(target.constructor)
? collectionHandlers
: baseHandlers
observed = new Proxy(target, handlers)
return observed
}
这里主要是用来判断Proxy进入哪个方法,基本上除了set、map、weakset 和weakmap,都是走baseHandlers方法。
proxy
let data = [1,2,3]
let p = new Proxy(data, {
get(target, key) {
console.log('获取值:', key)
return target[key]
},
set(target, key, value) {
console.log('修改值:', key, value)
target[key] = value
return true
}
})
p.push(4)
输出:
获取值: push
获取值: length
修改值: 3 4
修改值: length 4
Proxy的原理是在目标对象前设置一个拦截,当访问对象的时候,都必须经过这层拦截,也就是类似于代理,在外界访问对象的时候都可以实时进行过滤和更新对象。相对于defineproperty更厉害的地方就是数组和对象都可以直接触发getter和setter,但是数组会触发两次,因为获取push和修改length的时候也会触发。
Reflect
let data = [1,2,3]
let p = new Proxy(data, {
get(target, key) {
console.log('获取值:', key)
return Reflect.get(target,key)
},
set(target, key, value) {
console.log('修改值:', key, value)
return Reflect.set(target,key, value)
}
})
Reflect是一个内置对象,拥有一切javascript的操作方法,相对于Proxy负责对数组对象进行增删改查的监听操作,但是Vue3底层是通过Reflect获取对象的属性并进行增删改。也就是利用Proxy进行代理,再利用Relfect进行反射回应,最终和Proxy功能一一对应,更函数式标准化。