Angular Material Table接收新数据不自动刷新的原因排查
问题核心原因
你的表格不自动更新的本质原因是:connect()方法返回给表格的数据流,没有把数据变更的动作纳入可监听的触发源范围内。
当前你在connect()里合并的三个触发源分别是:
- 仅在初始化时发送一次固定值的
observableOf(this.data) - 分页组件的翻页事件
- 排序组件的排序变更事件
当你在getTableData()中直接给this.data赋值为接口返回的新数组时,这个赋值动作没有任何机制会推送信号给上述合并流,因此表格收不到任何需要重新渲染的通知。只有当你手动调整分页、排序时,这两个已有的触发源会向流内推送事件,流才会读取当前已经更新的this.data做处理并渲染到视图上,这就是你观察到的“必须调整排序/分页才会刷新”的根本原因。
具体修复步骤
1. 调整组件初始化顺序
你当前ngAfterViewInit内的执行顺序存在隐患:先调用getTableData()拉取数据,再给dataSource绑定sort和paginator,这会导致首次拉取数据时,dataSource的connect()方法因为检测不到已绑定的paginator和sort直接抛出错误。需要调整为:
- 先完成
sort、paginator与dataSource的绑定,再触发数据加载。
调整后的ngAfterViewInit代码:
ngAfterViewInit(): void { // 先完成表格依赖绑定 this.dataSource.sort = this.sort; this.dataSource.paginator = this.paginator; this.table.dataSource = this.dataSource; // 绑定完成后再加载数据 this.getTableData(); }
2. 给数据源增加可触发的数据变更通知流
在TableDataSource类中新增一个Subject作为数据变更的专属推送源,把它合并进connect()的返回流里,让数据更新的动作可以触发表格重新渲染:
- 类内新增私有通知源,替代原本只会发一次的静态observable:
private _dataChange$ = new BehaviorSubject<TableItem[]>([]); - 修改
connect()方法内的合并流逻辑,把数据变更源加入merge的触发列表:connect(): Observable<TableItem[]> { if (this.paginator && this.sort) { return merge( this._dataChange$, this.paginator.page, this.sort.sortChange ).pipe(map(() => { return this.getPagedData(this.getSortedData([...this.data])); })); } else { throw Error('Please set the paginator and sort on the data source before connecting.'); } } - 修改
getTableData()方法,拿到新数据赋值后,主动向通知源推送更新信号:public getTableData(): void { this.tableService.getTableItems() .subscribe(items => { this.data = items; // 数据更新完成后推送通知,触发表格重新渲染 this._dataChange$.next(this.data); }); }
修复后的效果
完成上述修改后,只要this.data被接口返回的新数据赋值并主动推送通知,合并流就会立刻触发,自动对新数据做排序、分页处理后发送给表格完成渲染,不需要用户手动调整分页或排序来触发刷新。
内容的提问来源于stack exchange,提问作者hullunist
相关产品推荐
相关产品推荐

