Angular中nui-checkbox赋值触发nuiChange致数组异常问题求助
问题
现有Angular项目中的nui-checkbox组件代码如下:
<nui-checkbox *ngFor="let optionManual of searchManuals | async" size="small" shape="round" fill="outline" (nuiChange)="selectManualOption(optionManual.manualId, $event.detail.checked)" [checked]="search.manualId.indexOf(optionManual.manualId) > -1"> <span slot="end" class="button-inner"><span class="product-code">{{ optionManual.productCode }}</span><span class="volume" *ngIf="optionManual.pmVolumeText"> {{ optionManual.pmVolumeText }}</span> <nui-pill> {{ optionManual.language }}</nui-pill> </span> <div class="button-effect"></div> </nui-checkbox>
新增过滤this.search.manualId数组的功能时,调用过滤函数会触发nui-checkbox的nuiChange事件,执行selectManualOption函数后出现数组元素异常丢失:
- 基础数组:
this.search.manualId = ['Banana', 'Apple', 'Strawberry', 'Peach', 'Melons'] - 过滤目标数组:
this.filterArray = ['Banana', 'Apple', 'Strawberry', 'Melons'] - 执行
this.search.manualId = this.filterArray后,最终数组丢失了预期的Peach和异常丢失的Melons
相关补充代码:
search对象初始化:
this.search = { id: -1, query: '', manualId: [], options: [] };
- 异步初始化数组:
this.searchManuals.then(manuals => { this.search.manualId = manuals.map(manual => manual.manualId); this.procedureManuals = manuals .filter(manual => PROCEDURE_MANUALS.includes(manual.productCode)) .map(manual => manual.manualId); });
- 过滤函数实现:
onSearchProcedureChecked(isChecked: boolean): void { if (isChecked) { this.search.manualId = this.procedureManuals; } else { this.search.manualId = this.allManuals; } }
解决方案
1. 添加过滤标记,跳过事件逻辑
新增一个类成员变量标记过滤状态,让selectManualOption在过滤期间不执行原有逻辑:
// 类内添加标记变量 isFiltering = false; // 修改过滤函数 onSearchProcedureChecked(isChecked: boolean): void { this.isFiltering = true; // 用扩展运算符创建新数组,避免引用共享导致的意外变更 this.search.manualId = isChecked ? [...this.procedureManuals] : [...this.allManuals]; // 延迟重置标记,确保Angular变更检测完成后恢复事件响应 setTimeout(() => this.isFiltering = false); } // 修改selectManualOption函数 selectManualOption(manualId: string, checked: boolean): void { if (this.isFiltering) return; // 原有逻辑保持,或改用不可变数组更新(见方案3) if (checked) { if (!this.search.manualId.includes(manualId)) { this.search.manualId.push(manualId); } } else { const idx = this.search.manualId.indexOf(manualId); if (idx > -1) this.search.manualId.splice(idx, 1); } }
2. 优化选中状态判断逻辑
将indexOf替换为更直观的includes,同时确保数组引用变更触发正确的变更检测:
<nui-checkbox *ngFor="let optionManual of searchManuals | async" size="small" shape="round" fill="outline" (nuiChange)="selectManualOption(optionManual.manualId, $event.detail.checked)" [checked]="search.manualId.includes(optionManual.manualId)"> <!-- 其余内容保持不变 --> </nui-checkbox>
3. 使用不可变数组更新
所有修改search.manualId的操作都创建新数组,避免直接修改原数组导致的组件异常触发:
selectManualOption(manualId: string, checked: boolean): void { if (this.isFiltering) return; if (checked) { if (!this.search.manualId.includes(manualId)) { this.search.manualId = [...this.search.manualId, manualId]; } } else { this.search.manualId = this.search.manualId.filter(id => id !== manualId); } }
内容的提问来源于stack exchange,提问作者Malkom
相关产品推荐
相关产品推荐

