文章目录
- vue3-为什么要用proxy代替defineProperty
- 1. 什么是Object。defineProperty,怎么实现的vue2响应式
- 2. proxy,专为代理对象而生
- 3. 总结
vue3-为什么要用proxy代替defineProperty
1. 什么是Object。defineProperty,怎么实现的vue2响应式
- 在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象
- 怎么实现呢
- 通过defineProperty的两个属性,get和set
- get
- get本质是属性的getter函数,说白了就是如果访问一个属性,会调用改属性的getter函数。getter返回的值就是属性的值
- set
- set本质是属性的setter函数,说白了就是如果给属性赋值,会调用该属性的setter函数,该方法接受一个参数,就是被赋予的新值
- 那具提怎么实现呢
function effect(){
console.log('我是副作用函数,我可以被触发')
}
function reactive(obj,key,val){
Object.defineProperty(obj,key,{
get(){
console.log(`get ${key}:${val}`)
return val
},
set(newVal){
if(newVal!==val){
val=newVal
effect()
}
}
})
}
let obj={
}
reactive(obj,'name','')
obj.name='tom'
- 调用reactive,数据发生变化时,会触发effect方法,实现数据响应式
- 如果有多个key就需要进行遍历
function observer(obj){
Object.keys(obj).forEach(key=>{
reactive(obj, key, obj[key])
})
}
function defineReactive(obj, key, val) {
observe(val)
Object.defineProperty(obj, key, {
get() {
console.log(`get ${key}:${val}`);
return val
},
set(newVal) {
if (newVal !== val) {
val = newVal
update()
}
}
})
}
- 通过这样的方式实现了基本的响应式,但是如果我们不是读取或者赋值,而是直接删除或者新增,或者对数组的API进行操作,这种响应式就无法劫持到了,于是增加了set,deleteAPI
- 但是如果存在较深的嵌套对象关系,会造成极大地性能问题
2. proxy,专为代理对象而生
- Proxy的监听是针对对象的,所以对象的所有操作都可以监听到,可以代理所有的属性
function reactive(obj){
if(typeof obj!=='object' && obj!==null){
return obj
}
const proxy=new Proxy(obj,{
get(target,key,receiver){
console.log('getter')
return Reflect.get(target,key,receiver)
},
set(target,key,value,reciever){
console.log('setter')
return Reflect.set(arget,key,value,reciever)
return isObject(Reflect.set(arget,key,value,reciever))?reactive(res):Reflect.set(arget,key,value,reciever)
},
deleteProperty(target,key){
console.log('delete')
return Reflect.deleteProperty(arget,key,value,reciever)
}
})
return proxy;
}
const obj=reactive({
name:'tom'
})
3. 总结
- defineProperty只能通过属性遍历,劫持属性
- proxy能对整个对象进行代理劫持