Vue数据响应式原理核心解读
在Vue中数据响应是其最大的特点,所谓数据响应就是当数据发生变化时,用户界面展示数据相应的做出改变,而开发者不需要手动的去操作DOM元素。
数据响应的原理其实也非常简单,在Vue3之前是通过 Object.defineProperty 方法实现,升级的Vue3后使用了ES6的新特性 Proxy 代理对象来实现。
为什么升级到Vue3就更换成 Proxy 呢? 原因很简单,从监听对象属性增删改查四个功能对比:
Object.defineProperty: 只能实现监听对象的改和查
Proxy: 全方位实现监听对象属性增删改查
对于 Object.defineProperty / Proxy 的用法不做过多讲解,想全面了解相关功能可以查阅官方文档。
Object.defineProperty实现
// 源数据
let data = {
name: '默认值',
age: 18
}
// 代理数据
let agent = {}
// 设置对象的属性描述
Object.defineProperty(agent, "name", {
// 开启属性可配置
configurable: true,
// 当获取该属性时自动调用
get() {
console.log("监听到读取属性,进行其他操作...")
return data.name
},
// 当设置该属性值时自动调用
set(value) {
console.log("监听到设置属性值,进行其他操作...")
data.name = value
},
})
// 继续设置对象的其他属性
Object.defineProperty(agent, "age", {
// 想设置什么属性就写几次。。。
})
// 读取属性 - 可以监听
let n = agent.name
// 更新属性 - 可以监听
agent.name = 'my name'
// 添加属性 - 无法监听
agent.sex = 2
// 删除属性 - 无法监听
delete agent.name
Proxy实现
// 源数据
let data = {
name: '默认值',
age: 18
}
// 代理数据
let agent = new Proxy(data, {
// 当获取该对象属性时自动调用
get(target, propName) {
console.log(`监听到读取对象属性:${propName},进行其他操作...`)
// 健壮写法: return Reflect.get(target, propName)
return target[propName]
},
// 当设置该对象属性值时自动调用
set(target, propName, value) {
console.log(`监听到设置或添加对象属性:${propName},进行其他操作...`)
// 健壮写法: return Reflect.set(target, propName, value)
target[propName] = value
},
// 当删除该对象属性时自动调用
deleteProperty(target, propName) {
console.log(`监听到删除对象属性:${propName},进行其他操作...`)
// 健壮写法: return Reflect.deleteProperty(target, propName)
return delete target[propName]
},
})
// 读取属性 - 可以监听
let n = agent.name
// 更新属性 - 可以监听
agent.name = 'my name'
// 添加属性 - 可以监听
agent.sex = 2
// 删除属性 - 可以监听
delete agent.name
// 已实现全方位监听