对象:通过defineProperty对对象的已有属性读取和修改进行劫持(监视/拦截);
数组: 通过重写数组更新数组一系列更新元素的方法来实现元素修改的劫持
缺点:
1、对象直接新添加的属性或删除已有属性, 界面不会自动更新
2、直接通过下标替换元素或更新length, 界面不会自动更新 (后来出了$set方法)
通过Proxy(代理): 拦截对data任意属性的任意(13种)操作, 包括属性值的增删改查
通过 Reflect(反射): 动态对被代理对象的相应属性进行特定的操作
解释:
Reflect(反射)
是一个内置的对象,(用来做反射的)它提供拦截 JavaScript 操作的方法。这些方法与proxy handlers (en-US)的方法相同。
Reflect不是一个函数对象,因此它是不可构造的。简单说就是 Reflect 可以将目标对象 的属性操作直接返回
Reflect.get(target, propertyKey[, receiver]) 获取对象身上某个属性的值,类似于 target[name]。
Reflect.set(target, propertyKey, value[, receiver]) 将值分配给属性的函数。返回一个Boolean,如果更新成功,则返回true。
Proxy (代理)
const p = new Proxy(target, handler)
参数:target对象 ===>>> 要使用 Proxy 包装的 目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。
参数:handler对象 ===>>> 一个通常以函数作为属性的 对象,各属性中的函数分别定义了在执行各种操作时代理 p 的行为。
必须使用两者结合实现响应式
// 目标对象
let user = {
name: '张三',
age:20,
car:{
name:'天籁',
monney:'20W'
}
}
// 把目标对象变成代理对象
const p = new Proxy(user,{
// get: function(target, property, receiver) {} target目标对象。property被获取的属性名。
get (target, property){
console.log('get方法被调用'); // undefined
return Reflect.get(target, property); // 参数和handler.get参数一样,可以将目标对象 的属性操作直接返回
},
// set: function(target, property, value, receiver){} target目标对象。property将被设置的属性名或 Symbol。value新属性值。receiver最初被调用的对象。通常是 proxy 本身,但 handler 的 set 方法也有可能在原型链上,或以其他方式被间接地调用(因此不一定是 proxy 本身)。
// 修改和添加目标对象的属性
set(target, property, value){
console.log('set方法被触发');
return Reflect.set(target, property, value)
},
// deleteProperty: function(target, property){} target目标对象。property待删除的属性名。返回值deleteProperty 必须返回一个 Boolean 类型的值,表示了该属性是否被成功删除
deleteProperty(target, property){
console.log(`${target.property}被删除了`);
return Reflect.deleteProperty(target, property)
}
})
p.name = '李四' // 改 触发 set
delete p.name; // 删 触发 deleteProperty
console.log(p); // 查 触发 get
p.name = 'hahah'; // 增 触发 set
console.log(p);