动态修改列配置时Ag-Grid无法显示数据的问题排查
问题:Ag-Grid动态列配置后数据无法显示,重复新增columnDefs
我在组件中使用Ag-Grid展示数据,通过API调用获取响应后动态提取数据列名,传递给子组件展示,但数据无法显示。使用静态列配置(直接从变量获取)时功能正常。
静态列配置
export let DETIALCONFIG= { columnDefs: [ { headerName: 'VT Name', field: 'vtName', hide: false, minWidth: 235, serverFlag: true, tooltipFields: 'veName' }, { headerName: 'Key', field: 'KEY', hide: false, serverFlag: true, }, { headerName: 'ID', field: 'ID', hide: true, serverFlag: true, }, { headerName: 'APP Name', field: 'APP_NAME', hide: true, minWidth: 140, serverFlag: true, }, { headerName: 'Status ', field: 'Status', hide: true, minWidth: 200, serverFlag: true, }, { headerName: 'Version', field: 'VERSION', hide: true, minWidth: 235, serverFlag: true, }, { headerName: 'Details', field: 'DETAILS', hide: true, minWidth: 235, serverFlag: true, }, { headerName: 'Json', field: 'JSON', hide: true, minWidth: 235, serverFlag: true, }, ], gridOptions: { domLayout: 'autoHeight', pagination: false, paginationPageSize: 6, rowSelection: 'multiple', enableColResize: true, enableSorting: true, enableFilter: true, suppressPropertyNamesCheck: true, enableBrowserTooltips: true, suppressAutoSize: true } }
动态逻辑代码
private run = async (veName: string) => { let response: any try { response = await apiCall(veName, [], true) this.veTableData = [...response.data] const keys = Object.keys(this.veTableData[0]) this.columnConfig = this.veDetailsGridConfig this.columnConfig.columnDefs.map((item: any) => { if(keys.includes(item.field)) { item.hide = false return item } }) console.log(this.columnConfig) this.tableHeader = veName.toUpperCase() } catch (err) { this.veTableData = [] this.columnConfig = this.veDetailsGridConfig } }
使用动态逻辑时,模板中gridOptions绑定columnConfig后,每次都会新增一组columnDefs,静态配置无此问题,推测这是数据无法显示的原因,需要排查问题。
解决方案
问题根源
- 原始配置对象被污染:
this.columnConfig = this.veDetailsGridConfig是直接赋值引用,而非创建新对象。每次修改columnDefs时都会直接修改原始的veDetailsGridConfig,导致后续调用时原始配置已经被修改,出现重复列的情况。 map方法使用错误:map不会修改原数组,你的代码仅在回调中修改item,但未将返回的新数组赋值回去;同时未对不匹配数据字段的列重置hide状态,导致之前的修改状态残留。
修复步骤
1. 深拷贝原始配置,避免污染
每次使用配置时,都要创建原始配置的深拷贝,确保每次操作的都是独立对象:
// 用JSON方法深拷贝(注意:如果配置中有函数,此方法不适用,需用递归深拷贝) this.columnConfig = JSON.parse(JSON.stringify(this.veDetailsGridConfig)); // 或者用扩展运算符手动拷贝(适合无函数的配置) this.columnConfig = { ...this.veDetailsGridConfig, columnDefs: this.veDetailsGridConfig.columnDefs.map(item => ({...item})) };
2. 正确设置列的显示/隐藏状态
使用forEach直接修改拷贝后的列配置,或用map返回新数组,确保所有列的hide状态都被正确重置:
// 方案1:forEach直接修改 this.columnConfig.columnDefs.forEach((item: any) => { // 匹配数据字段的列显示,不匹配的隐藏 item.hide = !keys.includes(item.field); }); // 方案2:map返回新数组(更符合不可变原则) this.columnConfig.columnDefs = this.columnConfig.columnDefs.map((item: any) => ({ ...item, hide: !keys.includes(item.field) }));
3. 处理空数据场景
如果API返回空数据,要避免调用Object.keys(this.veTableData[0])导致报错,提前做判断:
修复后的完整代码
private run = async (veName: string) => { let response: any try { response = await apiCall(veName, [], true) this.veTableData = [...response.data] // 处理空数据 if (this.veTableData.length === 0) { this.columnConfig = JSON.parse(JSON.stringify(this.veDetailsGridConfig)); this.tableHeader = veName.toUpperCase() return; } const keys = Object.keys(this.veTableData[0]) // 深拷贝原始配置 this.columnConfig = JSON.parse(JSON.stringify(this.veDetailsGridConfig)); // 统一设置列的显示隐藏 this.columnConfig.columnDefs.forEach((item: any) => { item.hide = !keys.includes(item.field); }) this.tableHeader = veName.toUpperCase() } catch (err) { this.veTableData = [] // 出错时也使用干净的拷贝配置 this.columnConfig = JSON.parse(JSON.stringify(this.veDetailsGridConfig)) } }
内容的提问来源于stack exchange,提问作者breakingcode
相关产品推荐
相关产品推荐

