一、Vue2中通过Object.defineProperty getter setter 实现对象的监听
Object.defineProperty监听弊端: 无法监听属性的添加或者移除;无法监听数组索引直接赋值;无法监听修改数组的长度
二、解决对象属性监听
对于对象属性的监听,vue提供了set delete方法
三、解决数组监听
修改数组的继承关系,重写方法,进行拦截调用。
修改后的继承关系为:arr(数组对象) -> 自定义的对象(他的隐式原型对象__proto__指向数组的显示原型对象prototype) -> Array.prototype
这个自定义的对象继承了Array的方法重写了push,pop,shift,unshift,splice,sort,reverse
const ARRAY_METHODS = ['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse]
const array_methods = Object.create(Array.prototype)
ARRAY_METHODS.formEach(method => {
array_methods[methos] = function() {
console.log(argument)
console.log('调用的是拦截的方法')
Array.from(arguments).forEach(arg => {
console.log('监听当前的参数')
})
// 当监听动作完成再进行函数调用
Array.prototyoe[method].apply(this, arguments)
}
})
-
如果浏览器支持__proto__,则采用修改原型链的方式
//.........
// 如果监听动作发生的时候,属性key的值value为数组 if (Array.isArray(value)) { value.proto = array_methods // .... }
2. 如果浏览器不支持__proto__,则采用混入发将方法拷贝到对象上面取
// 如果监听动作发生的时候,属性key的值value为数组
if (Array.isArray(value)) {
// getOwnPropertyNames返回的是对象所有自己的属性包含不可枚举
// Object.keys则返回的是所有可枚举的属性即enumerable: true
const array_keys = Object.getOwnPropertyNames(array_methods)
array_keys.forEach(key => {
Object.defineProperty(value, key, {
configurable: true,
writable: true,
enumerable: true,
value: array_methods[key]
})
})
}
四、VUE3中的实现
vue3中采用了Proxy对象的方式,实现对对象的拦截以及自定义操作。