关于数据劫持与数据代理
本文转自:《Js数据劫持与数据代理》
一、数据劫持
主要使用Object.defineProperty()实现
1 |
|
Object.defineProperty()的缺点:
- 无法监听到数组变化当被监听的属性是数组,这几个方法push、pop、shift、unshift、splice、sort、reverse不会触发set。vue将这几个修改原始的数组的方法称为变异方法
1
2
3
4
5
6
7
8
9
10
11
12
13//当被监听的属性是数组时
let arr = [1,2,3]
let obj = {}
Object.defineProperty(obj,'arr',{
get() {
return arr
},
set(newVal) {
arr = newVal
}
})
obj.arr.push(4) // 执行了get 实际上是改变arr的值但是却没有执行set而是执行了get
obj.arr = [1,2,3,4] // 执行了set - 必须遍历对象的每一个属性
1
2
3
4
5Object.keys(obj).forEach(key=>{
Object.defineProperty(obj,key,{
//....
})
}) - 必须深层遍历嵌套对象
当遇到变异方法时旧版本的vue通过重写方法来进行数据劫持
1 |
|
二、Proxy数据代理
劫持监听对象所发生的相应改变,并代理其做出相应改变
1 |
|
proxy的优点:
- 使用proxy可以解决defineProperty不能监听数组的问题,避免重写数组方法;
- 不需要再遍历key。
- Proxy handle的拦截处理器除了get、set外还支持多种拦截方式,具体请查阅官方文档(https://developer.mozilla.org...)
- 嵌套查询。实际上proxy get()也是不支持嵌套查询的。解决方法:
1
2
3
4
5
6
7
8
9let handler = {
get (target, key, receiver) {
// 递归创建并返回
if (typeof target[key] === 'object' && target[key] !== null) {
return new Proxy(target[key], handler)
}
return Reflect.get(target, key, receiver)
}
}