You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular Material表格清除过滤后子行数据源为空问题求助

问题解决思路

核心原因

JavaScript里对象、数组属于引用类型,你写的const filterdData = this.allData;只是把原数组的引用赋值给了变量,并没有复制新数据。主层级用filter()会返回全新数组,所以不会改动原allData;但处理子行时,你直接修改filterdData[index].subRows——这本质是在修改原allData里对应对象的subRows属性(因为它们指向同一块内存地址),导致过滤条件清空后,原数据的子行已经被改空,无法恢复。

修复方案

方案1:深拷贝原数据后操作

过滤前先对allData做深拷贝,确保操作的是完全独立的副本,不会影响原数据:

public filterDataSource(filters) {
   // 深拷贝原数据(适合无函数、Symbol等特殊类型的数据集)
   let filteredData = JSON.parse(JSON.stringify(this.allData));
   
   // 主层级过滤
   filteredData = filteredData.filter((x) => {
      return x.property.includes(filters.search);
   });

   // 子层级过滤,操作副本不影响原数据
   for(let index = 0; index < filteredData.length; index++) {
      filteredData[index].subRows = filteredData[index].subRows.filter((x) => {
         return x.property.includes(filters.search);
      });
   }
   
   this.dataSource.data = filteredData;
}

方案2:生成新对象处理子行(更高效)

如果不想深拷贝整个数组,可以在处理子行时为每个主对象创建新对象,只替换subRows属性,保留原对象的其他内容:

public filterDataSource(filters) {
   // 主层级过滤,返回新数组
   let filteredData = this.allData.filter((x) => {
      return x.property.includes(filters.search);
   });

   // 映射生成新对象,避免修改原数据的subRows
   filteredData = filteredData.map(item => {
      const filteredSubRows = item.subRows.filter(sub => sub.property.includes(filters.search));
      // 展开运算符创建新对象,继承原属性并替换subRows
      return { ...item, subRows: filteredSubRows };
   });
   
   this.dataSource.data = filteredData;
}

这个方案只复制需要修改的对象,性能更优,适合数据量较大的场景。

效果验证

修改后,清空过滤条件时,原allData的subRows会保持初始状态,过滤后的数据源会基于原数据重新生成,子行数据就能正常恢复。

内容的提问来源于stack exchange,提问作者Simon Damminga

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 13:24:57