Vue响应式数据之Array
修改原型方法
上面所说到的是对象的响应式,但 js 中不止有对象,还有数组,数组能用 Object.defineProperty 方式来监听吗,能
const original = Array.prototype.push
Array.prototype.push = function (...args) {
console.log('ADD', args)
return original.apply(this, args)
}
const arr = [1, 2, 3]
arr.push(4)
// 输出 ADD 4
当然,这里修改了全局的 Array 原 型,对于一些不必要的数据也会监听到,在 Vue2 中会进入 Observer 构造函数体,判断 value 是否为数组,是则对 value 原型赋值为修改后的 arrayMethods。
const arrayProto = Array.prototype
const arrayMethods = Object.create(arrayProto)
if (Array.isArray(value)) {
value.__proto__ = arrayMethods
}
至于以及其他数组方法,这里仅做代码实现,由于篇幅有限,不做细说。
const arrayProto = Array.prototype
const arrayMethods = Object.create(arrayProto)
function def(obj, key, val, enumerable) {
Object.defineProperty(obj, key, {
value: val,
enumerable: !!enumerable,
writable: true,
configurable: true,
})
}
;['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'].forEach(function (method) {
const original = arrayProto[method]
def(arrayMethods, method, function mutator(...args) {
const result = original.apply(this, args)
let inserted
switch (method) {
case 'push':
case 'unshift':
inserted = args
break
case 'splice':
inserted = args.slice(2)
break
}
if (inserted) {
console.log('ADD', args)
}
return result
})
})
function observerArray(arr) {
arr.__proto__ = arrayMethods
return arr
}
let arr = observerArray([1, 2, 3])
arr.push(4)
arr.unshift(0)
console.log(arr)