偵測(cè)數(shù)組中元素變化
偵測(cè)數(shù)組的變化類(lèi)比對(duì)Object的遞歸處理,我們也需要監(jiān)測(cè)子項(xiàng)的變化。
另外,數(shù)組與對(duì)象的使用需求有些不同,數(shù)組要求新增的項(xiàng)依然能夠被監(jiān)測(cè)到(想象你對(duì)一個(gè)響應(yīng)式的數(shù)組push一個(gè)子數(shù)組,后面操作這個(gè)子數(shù)組時(shí),頁(yè)面沒(méi)反應(yīng),就顯得奇怪了?。?/em>。
首先做對(duì)子項(xiàng)的偵測(cè):
export class Observer{
constructor(value){
this.value = value;
def(value, '__ob__', this);
if(Array.isArray(value)){
this.observeArray(value);
} else {
this.walk(value);
}
}
observeArray(items){
for(let i = 0, l = keys.length;i < l;i++){
observe(items[i]);
}
}
}
像這樣對(duì)數(shù)組進(jìn)行遞歸的處理就可以做到子項(xiàng)變成響應(yīng)式的了。
偵測(cè)新增元素的變化
[
'push',
'pop',
'shift',
'unshift',
'splice',
'sorte',
'reverse'
].forEach(function(method){
const original = arrayProto[method];
def(arrayMethods, method, function mutator(...args){
const ob = this.__ob__;
let inserted;
switch(method){
case 'push':
case 'unshift':
inserted = args;
break;
case 'splice':
inserted = args.slice(2);
break;
}
ob.dep.notify();
return original.apply(this, args);
})
})
不難發(fā)現(xiàn)九個(gè)方法中,可以新增元素的只有前插、后插和插入操作,捕捉響應(yīng)的參數(shù)就好了。
獲取的到新增元素的話就可以遞歸的把這些變成響應(yīng)式數(shù)據(jù)了。
[
'push',
'pop',
'shift',
'unshift',
'splice',
'sorte',
'reverse'
].forEach(function(method){
const original = arrayProto[method];
def(arrayMethods, method, function mutator(...args){
const ob = this.__ob__;
let inserted;
switch(method){
case 'push':
case 'unshift':
inserted = args;
break;
case 'splice':
inserted = args.slice(2);
break;
}
if(inserted) ob.observeArray(inserted); // 新增
ob.dep.notify();
return original.apply(this, args);
})
})
偵測(cè)數(shù)組的缺陷
由于是通過(guò)攔截原型方法完成響應(yīng),因此,對(duì)于通過(guò)[]直接修改和對(duì)length的賦值無(wú)法偵測(cè)。
this.list[0] = 2;
this.list.length = 0;