这是我参与8月更文挑战的第28天,活动详情查看: 8月更文挑战
前言
Vue 2.x是利用Object.defineProperty()方法侦测对象的属性变化,但该方法有一些固有的缺陷:
- 性能较差
- 在对象上新增属性是无法被侦测的
- 改变数组的length属性时无法被侦测的
Vue 3.0 响应式系统的实现原理
Vue 3.0使用ES6的Proxy取代Object.defineProperty()方法,性能更优异,而且数组和对象一样,可以直接触发get()和set()方法。Proxy称为代理,是一种可以拦截并改变底层JavaScript引擎操作的包装器。
调用new Proxy(target, handler)可以为一个目标对象创建一个代理,代理可以拦截JavaScript引擎内部目标的底层对象操作,这些底层操作被拦截后会触发响应特定操作的陷阱函数。在调用Proxy构造函数时,需要传入两个参数,target为目标对象;handler是一个包含陷阱函数的处理器对象中。
// 处理器对象
const baseHandler = {
// 陷阱函数,读取属性值时触发
// 参数target是目标对象
// 参数property是要获取的属性名
// 参数receiver是Proxy对象或继承Proxy的对象
get(target, property, receiver){
console.log('获取值')
},
// 陷阱函数,写入属性值时触发
// 参数value是新的属性值
set(target, property, value, receiver){
console.log('设置值')
},
// 陷阱函数,删除属性值时触发
deleteProperty(target, property){
console.log('删除属性')
}
}
// 目标对象
const target = {name: 'jack'}
// 为目标对象创建代理对象
const proxy = new Proxy(target, baseHandler)
// 读取属性值
proxy.name
// 设置属性值
proxy.name = 'tom'
// 删除属性
delete proxy.name
之后,针对代理对象的相关操作就会触发处理器对象中的对应陷阱函数,在陷阱函数中就可以为目标对象的属性访问添加自定义的业务逻辑。
上述代码的运行结果为:
获取值
设置值
删除属性