1. 问题复现
快速在两个tab之间来回点击多次后,造成页面死循环:在这两个tab之间不停来回切换
2. 代码实现
- html
<nz-tabset
(nzSelectChange)="onTabChange($event)"
[(nzSelectedIndex)]="selectedTabIndex"
>
- ts
// 切换tab
public onTabChange(event: NzTabChangeEvent) {
const {index} = event;
const type = this.routerLinkList[index];
this.router.navigate(['.'], {
queryParams: {type},
queryParamsHandling: 'merge',
});
}
// 监听路由参数变化
private watchRoute() {
this.route.queryParams.subscribe((params) => {
this.selectedTabIndex = this.tabTitleList.findIndex(
(item) => item.key === type
);
});
}
3. 原因分析
private watchRoute() {
this.route.queryParams.subscribe((params) => {
this.selectedTabIndex = this.tabTitleList.findIndex(
(item) => item.key === type
); // 此方法为异步操作,对selectedTabIndex赋值前后,值可能不一致,触发nzSelectChange事件,造成死循环
});
}
问题模型:
onTabChange(A) 触发异步方法watchRoute(B): A=>B- B方法中对
selectedTabIndex的赋值又会触发A: B=>A 步骤2是有条件触发:基于angular变更监测,selectedTabIndex赋值前后若值有变则触发onTabChange事件,所以这是一个偶现问题
4. 解决
watchRoute的目的是根据路由参数选中对应的nz-tab,这个只需要在首次加载时有用
// 监听路由参数变化
private watchRoute() {
this.route.queryParams.subscribe((params) => {
// 首次加载时再选中
if (isFirstLoad) {
this.selectedTabIndex = this.tabTitleList.findIndex(
(item) => item.key === type
);
this.isFirstLoad = false;
}
});
}