Angular9 子组件ngx-datatable二次加载时无法显示全部行问题
问题根因
这个异常是ngx-datatable开启虚拟滚动后的状态残留bug导致的:
- 你配置了
[scrollbarV]="true"启用虚拟滚动,组件内部会缓存上一次数据源对应的滚动偏移量、视口渲染范围、行高计算结果 - 第二次切换国家传入新的州数据时,组件没有自动重置内部缓存的虚拟滚动状态,直接沿用上一次的视口计算逻辑,只会渲染初始视口匹配的行,绝大多数场景下就只显示1行
- 直接用展开运算符做浅拷贝赋值
this.rows = [...states]时,如果新旧数组长度差异较大,没有触发表格全量变更检测,会进一步放大这个渲染问题
修复方法
1. 主动重置表格虚拟滚动状态
通过ViewChild获取表格实例,每次切换数据源前清空旧状态,再赋值新数据:
首先在ts文件引入表格组件,绑定模板里的#dataTable实例:
import { DatatableComponent } from '@swimlane/ngx-datatable'; // 组件类内 @ViewChild('dataTable') stateTable: DatatableComponent;
修改原有的editCountry方法逻辑:
editCountry(country: Country, states: StateViewModel[]){ if (!country) return; // 处理序号 states.forEach((state, index) => { (state as any).index = index + 1; }); this.rowsCache = [...states]; // 先清空旧数据,重置滚动状态 this.rows = []; this.stateTable.offset = 0; this.stateTable.scrollToPosition(0, 0); // 等状态重置完成后再赋值新数据,触发表格重算 setTimeout(() => { this.rows = [...states]; this.stateTable.recalculate(); }, 0); }
2. 配置行追踪属性,避免错误复用DOM
给ngx-datatable增加trackByProp配置,让组件按数据唯一标识追踪行变更,不要复用错误的行DOM实例:
<ngx-datatable #dataTable [rows] = "rows" [rowHeight]="35" [headerHeight]="35" [footerHeight]="35" [columns]="columns" [scrollbarV]="true" [columnMode]="'force'" [trackByProp]="'id'"> <!-- 替换为你StateViewModel里的唯一主键字段,比如stateId --> </ngx-datatable>
3. 兜底方案:销毁重建表格
如果前两步操作后仍有渲染异常,直接用*ngIf在切换数据时先销毁表格再重建,彻底清除所有残留状态:
模板调整:
<ngx-datatable *ngIf="tableVisible" #dataTable <!-- 其余原有配置保持不变 --> > </ngx-datatable>
ts逻辑调整:
// 组件类内初始化 tableVisible = true; editCountry(country: Country, states: StateViewModel[]){ if (!country) return; states.forEach((state, index) => { (state as any).index = index + 1; }); this.rowsCache = [...states]; // 先销毁表格 this.tableVisible = false; this.rows = [...states]; // 下一变更检测周期重建表格 setTimeout(() => { this.tableVisible = true; }, 0); }
注意:传入的states数组如果是父组件持有的引用,最好先做一次深拷贝再处理,避免直接修改原数组引发父组件的变更检测混乱。
内容的提问来源于stack exchange,提问作者kavya
相关产品推荐
相关产品推荐

