Vue2
对象类型: 通过Object.defineProperty()对属性的读取,修改进行拦截(数据劫持)
数组类型:通过重写更新数组的一系列方法实现拦截。(对数组的变更进行了包裹)
底层实现:
通过对象属性拦截的方式实现,但是无法监听删除和添加
const person = {
name: 'ls',
age: 17
}
// 静态代理的方式实现 用p 来代理 person
const p = {}
Object.defineProperty(p, 'name', { // Object.keys(person) 循环每一个属性执行 Object.dfineProperty() 实现每个属性的代理
configurble: true, // 允许删除
// 有人读取 name 时触发
get() {
return person.name // 将读取的结果返回
},
// 有人修改 name 时触发
set(value) { // 修改后的值
person.name = value // 将值修改
}
})
缺点:
对象类型: 新增属性、删除属性,界面不更新
数组类型: 直接通过下标修改数组,界面不会更新
解决方法:
数组可以使用vue.set()方法和数组的splice方法
置空数组重新赋值也行
// 对象类型
vue.$set(要修改的对象, 添加的属性名,属性值)
this.$set() // 同上
this.$delete(要修改的对象,要删除的属性名)
// 数组类型
this.$set(要修改的数组, 下标, 值)
this.$delete(要修改的数组,下标)
Array.splice(0,1, '逛街') // 也能解决 或者置空数组重新赋值
Vue3
通过Proxy对象整体代理,拦截对象中任意属性的变化,包括属性的读写,属性的添加,属性的删除等等
通过Reflect反射对象:对原文件进行操作
const person = {
name: 'ls',
age: 17
}
const p = new Proxy(person, {
// 读取p某个属性时调用 target为原对象 propName为读取的属性
get(target, propName) {
// 参数一 要查找的对象 不是对象会报错
// 参数二 要查找的属性
// 参数三 如果读取的对象属性部署了读取函数getter,则读取函数的this绑定参数三
return Reflect.get(target, propName) // 返回读取的结果,没有属性则返回undefined 不会报错,更有利于框架的开发
},
// 有人修改person的某个属性,或给person追加某个属性时调用
set(target, propName, value) { // target为原对象 propName为修改或增加的属性,value修改或增加的值
// 参数一 要修改的对象
// 参数二 要修改的属性
// 参数三 修改的值
// 参数四 同上述Reflect.get方法参数三描述
return Reflect.set(target, propName, value) // 返回布尔值表示是否删除属性成功
},
// 有人删除 person 的某个属性时调用
deleteProperty(target, propName) { // target为原对象 propName为删除的属性
// 等同于 delete obj[name] 用于删除对象中的属性
return Reflect.deleteProperty(target, propName) // 返回一个布尔值,成功为true,反之为false
}
})