1.实现原理
对象类型:通过Object.defineProperty()
对属性的读取、修改进行拦截(数据劫持)。
数组类型:通过重写更新数组的一系列方法来实现拦截。(对数组的变更方法进行了包裹)。
2.存在问题
① 新增属性、删除属性, 界面不会更新。
② 直接通过下标修改数组, 界面不会自动更新。
3.Vue2解决这些问题的方法:
① 针对对象新增和删除,引入$set方法,属性添加:this.$set(this.person,'sex','女'),属性删除:this.$delete(this.person,'sex','女') 三个参数分别是:增加或要删除的对象、属性名、属性值
② 数组的修改,使用splice,this.person.hobby.splice(0,1,'逛街') 三个参数:删除的下标、删除个数、替换成什么
4.模拟Vue2中的响应式原理:
//源数据
let person = {
name: '张三',
age: 18
}
//模拟Vue2中实现响应式
let p = {}
Object.defineProperty(p,'name',{
configurable:true,
get(){ //有人读取name时调用
return person.name
},
set(value){ //有人修改name时调用
console.log('有人修改了name属性,我发现了,我要去更新界面!')
person.name = value
}
})
Object.defineProperty(p,'age',{
get(){ //有人读取age时调用
return person.age
},
set(value){ //有人修改age时调用
console.log('有人修改了age属性,我发现了,我要去更新界面!')
person.age = value
}
})
5.Vue3中的响应式原理实现原理
① 通过Proxy(代理): 拦截对象中任意属性的变化, 包括:属性值的读写、属性的添加、属性的删除等。
② 通过Reflect(反射): 对源对象的属性进行操作。
6.存在问题
暂没发现,可以解决Vue2中出现的问题
7.模拟实现
const p = new Proxy(person, {
//有人读取p的某个属性时调用
// target就是person原对象
get(target, propName) {
console.log(`有人读取了p身上的${propName}属性`)
return Reflect.get(target, propName)
},
//有人修改p的某个属性、或给p增加某个属性时调用
set(target, propName, value) {
console.log(`有人修改了p身上的${propName}属性,我要去更新界面了!`)
Reflect.set(target, propName, value)
},
//有人删除p的某个属性时调用
deleteProperty(target, propName) {
console.log(`有人删除了p身上的${propName}属性,我要去更新界面了!`)
return Reflect.deleteProperty(target, propName)
}
})
8.补充:Reflect:反射对象,对源对象的属性进行增删改查