vue2响应式:基于object.defineProperty()实现的
vue3响应式:基于proxy实现的
两者的区别:
vue2
// vue2
function defineReactive(data, key, val) {
Object.defineProperty(data, key, {
get: function () {
console.log(`对象属性:${key}访问defineReactive的get!`)
return val
},
set: function (newVal) {
if (val !== newVal) {
val = newVal
}
console.log(`对象属性:${key}访问defineReactive的set!`)
}
})
}
const data = {
name: "mingming",
age: 18
}
Object.keys(data).forEach(key => {
defineReactive(data, key, data[key])
})
//console.log(data.name)//对象属性:name访问defineReactive的get! mingming
//编辑属性
data.name = "honghong"
//console.log(data.name)//对象属性:name访问defineReactive的set! honghong
//添加属性
data.hobby = "篮球"
console.log(data.hobby) //篮球
弊端:data中新增了hobby属性。进行访问和设置,但是都不会触发get和set
所以Object。defineProperty只对初始对象里的属性有监听作用,而对新增的属性无效。这也是vue2中对象新增属性的修改使用vue。$set来设置的原因
vue3
// vue3
const data = {
name: "mingming",
age: 18
}
function defineReactive(target) {
const handler = {
get(target, key, receiver) {
//target:对象 key:属性 receiver:proxy类型的对象
console.log(`对象属性:${key}访问defineReactive的get!`)
return Reflect.get(target, key, receiver);
},
set(target, key, value, receiver) {
console.log(`对象属性:${key}访问defineReactive的set!`)
Reflect.set(target, key, value, receiver);
}
}
return new Proxy(target, handler)
}
const proxyData = defineReactive(data)
console.log(proxyData.name)//对象属性:name访问defineReactive的get! mingming
proxyData.hobby = "篮球";
console.log(proxyData.hobby) //对象属性:hobby访问defineReactive的set! 篮球
proxyData.hobby = "打游戏";
console.log(proxyData.hobby) //对象属性:hobby访问defineReactive的set! 打游戏
vue3核心原理
链接地址:https://mp.weixin.qq.com/s/v-0Mib0LbwCKxS00AmXwig