简略模拟vue2.x响应式的实现
let person = {
name: 'AIpoem',
age: 20
}
// 简略模拟vue2中实现响应式
let p = {};
Object.defineProperty(p, 'name', {
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;
}
})
我们新增一个属性或者删除已有属性,是无法被捕获到的,能被捕获到的操作只有读取和修改,这就是vue2中响应式的局限性
简略模拟vue3.0响应式的实现
let person = {
name: 'AIpoem',
age: 20
}
// 简略模拟vue3中实现响应式
const p = new Proxy(person, {
// target为源对象,即传入的person,prop是被人读取的属性
// get在有人读取p的某个属性时调用
get(target,prop) {
return Reflect.get(target,prop);
},
// target为源对象,即传入的person,prop是被人修改的属性或新增的属性,value是修改后的值
// set在有人修改或添加某个属性时调用
set(target,prop,value) {
console.log(`${prop}属性被修改了,这里执行更新界面的操作——————`);
Reflect.set(target,prop,value);
},
// deleteProperty在有人删除p的某个属性时调用
deleteProperty(target,prop) {
console.log(`${prop}属性被删除了,这里执行更新界面的操作——————`);
return Reflect.deleteProperty(target,prop)
}
})
总结
vue2.x的响应式
- 实现原理:
- 对象类型:通过
Object.defineProperty()
对属性的读取、修改进行拦截(数据劫持) - 数组类型:通过重写更新数组的一系列方法来实现拦截(对数组的变更方法进行了包裹)
- 对象类型:通过
- 存在问题:
- 直接新增、删除属性,界面不会更新
- 直接通过下标修改数组,界面不会更新
vue3.0的响应式
- 实现原理:
- 通过
Proxy
(代理):拦截对象中任意属性的变化,包括:属性值的读写、属性的添加、属性的删除等 - 通过
Reflect
(反射):对源对象的属性进行操作
- 通过
new Proxy(data,{
// 拦截读取属性值
get(target,prop) {
return Reflect.get(target,prop);
},
// 拦截设置属性值或添加新属性
set(target,prop,value) {
Reflect.set(target,prop,value);
},
// 拦截删除属性
deleteProperty(target,prop) {
return Reflect.deleteProperty(target,prop);
}
});