最近寫項(xiàng)目的時(shí)候设易,碰到個(gè)問題:
請(qǐng)求的數(shù)組中某個(gè)字段需要執(zhí)行請(qǐng)求進(jìn)行二次渲染逗柴,在遍歷原數(shù)組執(zhí)行異步請(qǐng)求的時(shí)候,碰到了兩個(gè)問題顿肺,第二個(gè)問題是因?yàn)榈谝粋€(gè)問題解決之后出現(xiàn)的新問題嚎于。。挟冠。替梨。
第一個(gè)問題:數(shù)組遍歷執(zhí)行異步請(qǐng)求后通過push到新數(shù)組導(dǎo)致順序可能會(huì)發(fā)生改變
第二個(gè)問題:循環(huán)遍歷未結(jié)束時(shí)德迹,新數(shù)組就已經(jīng)賦值給原數(shù)組了沪蓬,導(dǎo)致控制臺(tái)報(bào)某個(gè)字段undefined
解決第一個(gè)問題的辦法:
在循環(huán)原數(shù)組進(jìn)行遍歷的時(shí)候括蝠,可以攜帶索引,然后將請(qǐng)求結(jié)果賦值新數(shù)組的時(shí)候按照索引進(jìn)行插入控淡,這樣新數(shù)組順序跟原數(shù)組順序就是一樣的了
再通過索引改變新數(shù)組的時(shí)候可能存在個(gè)問題:
Vue官網(wǎng)上的:
由于 JavaScript 的限制嫌吠,Vue 不能檢測以下數(shù)組的變動(dòng):
1.當(dāng)你利用索引直接設(shè)置一個(gè)數(shù)組項(xiàng)時(shí),例如:vm.items[indexOfItem] = newValue
2.當(dāng)你修改數(shù)組的長度時(shí)掺炭,例如:vm.items.length = newLength
為了解決第一類問題辫诅,以下兩種方式都可以實(shí)現(xiàn)和vm.items[indexOfItem] = newValue
相同的效果,同時(shí)也將在響應(yīng)式系統(tǒng)內(nèi)觸發(fā)狀態(tài)更新:
// Vue.set
Vue.set(vm.items, indexOfItem, newValue)
// Array.prototype.splice
vm.items.splice(indexOfItem, 1, newValue)
你也可以使用 vm.$set
實(shí)例方法涧狮,該方法是全局方法 Vue.set
的一個(gè)別名:
vm.$set(vm.items, indexOfItem, newValue)
第二個(gè)問題:因?yàn)閖s是單線程炕矮,執(zhí)行遍歷的時(shí)候下面的賦值操作可能就已經(jīng)結(jié)束了么夫,然后新數(shù)組在遍歷完成之前都是空數(shù)組,這才導(dǎo)致了某個(gè)字段取不到肤视。
解決辦法:在執(zhí)行遍歷前聲明一個(gè)索引档痪,每執(zhí)行一次遍歷結(jié)束索引加1,如果索引等于原數(shù)組長度邢滑,說明執(zhí)行完成腐螟,此時(shí)在進(jìn)行賦值即可
private getDataSourceFilter(dataSource: ResourceInfo[]) {
let newDataSource: ResourceInfo[] = [];
let idx = 0;
dataSource.forEach(async (item: ResourceInfo, index: number) => {
let areaName = "";
const PromiseAll = [
HttpRequest.getAreaInfoById({ areaId: item.cityId }),
HttpRequest.getAreaInfoById({ areaId: item.countyId })
];
const resAll = await Promise.all(PromiseAll);
if (resAll) {
resAll.forEach((resItem: any) => {
if (resItem && resItem.data) {
areaName += resItem.data.areaName;
} else {
areaName += "";
}
});
const newItem = Object.assign(item, { areaName });
// newDataSource.push(newItem);
/**
* Vue.set
*/
Vue.set(newDataSource, index, newItem);
idx += 1;
if (dataSource.length === idx) {
this.dataSource = newDataSource;
this.loading = false;
}
}
});