八、添加数组的方法
“ 自己动手实践,就会更加深刻的理解**”**
这次处理数组的七个方法,使其成为响应式。
01、获取数组原型对象
重写每一个函数不现实,所以打算先获取数组的原型对象,然后生成一个新的对象来继承此原型对象,这个新的对象就拥有数组的一切属性方法,且不会对原生的数组产生任何影响。
/**
* 对与响应式数组,我们需要重写其一些方法,例如 push、pop
* 保证响应式数组使用这些方法之后依然是响应式的。
*/
const arrProto = Array.prototype;
const arrMethods = Object.create(arrProto);
02、重写方法
我们需要覆盖七个方法:
const methodsToPatch = [ 'push', 'pop', 'shift', 'unshift', 'sort', 'reverse', 'splice',]
对于 **push, pop, splice**,响应式数组唯一不同的地方在于,对于往数组新加的数据项,需要保证其仍然是响应式的。其他的方法,要么是更改数据的位置,要么是删除某些数据,都不需要额外的处理,只需调用原来的方法即可。
function def(obj, key, val, enumerable) {
Object.defineProperty(obj, key, {
value: val,
enumerable: !!enumerable,
configurable: true,
writable: true,
})
}
methodsToPatch.forEach(method => {
const original = arrMethods[method];
def(arrMethods, method, function mutate() {
console.log('调用的方法是:', method);
let args = [], len = arguments.length;
while (len--) args[len] = arguments[len];
const result = original.apply(this, args);
let inserted;
const ob = this.__ob__;
switch(method) {
case 'push':
case 'unshift':
inserted = args; break;
case 'splice':
inserted = args.slice(2); break;
}
// 如果有新增的数据,则每个数据都将其响应式化
if (inserted) {
ob.observeArray(inserted);
}
return result;
})
})
03、效果图
数据初始化:
const data = {
name: 'romeo',
message: 'wants to be rich',
deep: {
firstLevel: {
secondLevel: 'here!'
}
},
arr: [
{ name: 'jack1' },
{ name: 'jack2' },
{ name: 'jack3' },
]
}
可以看到 arr 中确实拥有了第四项,且同样是响应式的。
源代码在github上,请点击阅读原文查看~