vue2.x的响应式
-
实现原理
- 对象类型:通过
Object.defineProperty()
对属性的读取、修改进行拦截(数据劫持) - 数组类型:通过重写更新数组的一系列方法来实现拦截(对数组的变更方法进行了包裹)
- 对象类型:通过
-
存在的问题
- 新增属性、删除属性 界面不会更新
- 直接通过下标修改数组 界面不会自动更新
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33// 源数据
let person = {
name: '张三',
age: 22
}
let p = {}
Object.defineProperty(p, 'name', {
configurable: true,
// 读取name时调用
get() {
console.log('有人读取了name属性,我发现了,我要去更新界面!')
return person.name
},
// 修改name时调用
set(value) {
console.log('有人修改了name属性,我发现了,我要去更新界面!')
person.name = value
}
})
Object.defineProperty(p, 'age', {
configurable: true,
// 读取name时调用
get() {
console.log('有人读取了name属性,我发现了,我要去更新界面!')
return person.age
},
// 修改name时调用
set(value) {
console.log('有人修改了name属性,我发现了,我要去更新界面!')
person.name = age
}
})
vue3.x的响应式
-
实现原理
- 通过Proxy(代理):拦截对象中任意属性的变化,包括:属性值的读写、添加删除等
- 通过Reflect(反射):对源对象的属性进行操作
- MDN文档中描述的Proxy与Reflect:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22// 源数据
let person = {
name: '张三',
age: 22
}
const p = new Proxy(person, {
// 有人读取p的某个属性时调用
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)
}
})