ExtJs 6.7.0 TreePanel锁定列时rowWidget展开错位问题求解
问题现象
- 为搭载
Ext.grid.Panel类型rowWidget的Ext.tree.Panel首列配置locked: true锁定属性后,触发rowWidget展开时无法同步撑开锁定列区域,出现行内容错位问题。 - 开启列锁定功能后,树/表格组件会拆分为两个同步联动的网格,分别承载锁定列、非锁定列内容,默认逻辑下rowWidget的展开动作仅作用于非锁定列区域,未同步生效到锁定列侧。
- 移除首列的
locked: true配置后,组件rowWidget展开、收起逻辑运行正常,无错位问题。
问题根因
Ext JS锁定列的底层实现是将原面板拆分为两个独立的网格实例:lockedGrid承载锁定列内容,normalGrid承载非锁定列内容。二者默认仅同步滚动、行选中这类基础交互,未绑定rowWidget的展开状态、行高同步逻辑。
rowWidget触发展开时,只会在所属网格内生成widget组件、更新对应行高,另一侧网格既不会生成对应widget实例,也不会同步更新行高,最终两侧行高不匹配,触发内容错位。
修复方案
通过扩展树面板逻辑,绑定两侧网格的rowWidget状态同步即可解决问题,核心实现逻辑:
- 面板渲染完成后,校验是否存在锁定列拆分的双网格结构,仅在开启锁定列时启用同步逻辑
- 增加同步锁标记,避免双向事件监听触发死循环
- 同时监听两侧网格的
expandbody、collapsebody事件,任意一侧触发展开/收起时,同步调用另一侧对应记录行的展开/收起方法 - 展开/收起过程中同步两侧对应行的高度,消除高度差导致的错位
核心实现代码:
Ext.define('Ext.ux.fix.LockedTreeRowWidgetSync', { override: 'Ext.tree.Panel', initComponent: function () { this.callParent(arguments); this.on('afterrender', this._bindRowWidgetSync, this, {single: true}); }, _bindRowWidgetSync: function () { const lockedGrid = this.lockedGrid, normalGrid = this.normalGrid; // 未开启锁定列时无需绑定 if (!lockedGrid || !normalGrid) return; let syncFlag = false; const syncAction = (sourceGrid, record, isExpand, sourceRow) => { if (syncFlag) return; syncFlag = true; const targetGrid = sourceGrid === lockedGrid ? normalGrid : lockedGrid, targetView = targetGrid.getView(), targetRow = targetView.getRow(record); if (targetRow) { const isTargetExpanded = targetRow.classList.contains('x-grid-row-expanded'); // 状态不一致时同步展开/收起 if (isExpand !== isTargetExpanded) { targetView.toggleRowExpansion(record, isExpand); } // 同步行高 targetRow.style.height = isExpand ? `${sourceRow.offsetHeight}px` : ''; } syncFlag = false; }; // 给两侧网格绑定事件 [lockedGrid, normalGrid].forEach(grid => { const view = grid.getView(); view.on('expandbody', (rowNode, record) => { syncAction(grid, record, true, rowNode); }); view.on('collapsebody', (rowNode, record) => { syncAction(grid, record, false, rowNode); }); }); } });
补充说明:如果rowWidget内部承载交互类组件(表单、按钮组等),需要额外增加两侧widget实例的数据同步逻辑,避免同一条记录对应的两个widget实例数据状态不一致。
内容的提问来源于stack exchange,提问作者Luchini
相关产品推荐
相关产品推荐

