vue2响应式的原理是通过Object的一个方法,definProperty把一个对象的某个属性变成一个get和set函数,他是针对对象的某个属性的,他需要对对象进行深度遍历,对每个属性进行监听,当访这个属性或者修改时就会触发get和set函数.
const obj ={
a:1,
b:2,
c:{
a:1,
b:2,
};
function _isObject(v){
return typeOf v === 'object' && v != null
}
function observe(obj){
//我们要对传进来的每个对象进行遍历
for(const k in obj){
let v = obj[k];
//如果遍历的时候该属性是一个对象,则在遍历一次
if(_isObject(v)){
observe(v)
}
Object.defineProperty(obj,k,{
get(){
console.log('a','读取')
return v
},
set(val){
if(val!==v){
console.log('a','更改')
v=val
}
}
})
}
}
//观察
observe(obj)
这就是vue2响应式的做法,而他有一个天生的缺陷,他是针对每个属性的监听,所有他必须进行深度遍历,这会有效率的损失,由于他在观察这个步骤里面已经对对象进行了深度遍历,在这个时间里对象里面有的属性都被监听到了,都被改成get和set函数了,但是这个步骤一旦做完了,你去对这个对象进行新增,删除操作他是不知道的,因为监听步骤已经结束了, 在created钩子函数之前已经对对象进行了监听
vue3则是通过proxy对对象进行监听,他和vue2不同之处就是他是对整个对象进行监听,vue2的做法是直接去遍历对象的每一个属性,改动原始对象,监听他的每一个属性,而vue3则是产生一个新的代理对象,不会去动原始对象,后续对这个对象的每一个操作都是去操作这个代理对象
//代理,后续对这个属性读取或者修改则是直接通过这个代理去做的
function observe(obj){
const proxy = new Proxy(obj,{
//obj是读取的那个对象 k就是那个值
get(obj,k){
let v = obj[k]
if(_isObject(v)){
v=observe(v)
}
console.log(k,'读取')
return v
},
set(obj,k,val){
if(obj[k]!==val){
obj[k]=val;
console.log(k,'更改')
}
}
})
return proxy
}
//生成代理对象
const proxy = observe(obj)