ExtJS 4.2 Grid单元格合并实现技巧
ExtJS4 2Grid单元格合并通过操作tr和td的rowspan属性实现,重复行隐藏。多列合并分逐个列与全部列两种方式,提供mergeGrid函数代码,支持指定列索引及是否全部列相同才合并。
ExtJS 4.2 的 Grid 组件默认不具备单元格合并功能,需要开发者手动实现。本文将深入拆解实现原理与核心代码,帮助你快速掌握合并技巧,避免常见问题。
目录
1. 原理
2. 多列合并
3. 代码与在线演示
1. 原理
1.1 HTML 代码分析
首先创建一个基础的 Grid 组件,然后观察其生成的 HTML 结构。


通过分析生成的 HTML 可以看出,Grid 组件主要分为 grid-header 和 grid-body 两大区域(若启用了工具栏或分页栏,则会额外拥有独立的区域)。
在 grid-body 内部,包含若干 tr 元素,每个 tr 对应 Grid 中的一行数据;每个 tr 中又包含多个 td,每个 td 就是一个具体的单元格。

1.2 原理
步骤说明
整个合并操作的核心都围绕 tr 元素展开,具体流程如下:
- 比较第一行
tr与第二行tr的某个td的值,若两行的内容相等:将第一行tr的该td的rowspan属性值增加 1,并将第二行tr的对应td隐藏。 - 接着拿第一行
tr与第三行tr比较,若值仍相等:第一行的rowspan再增加 1,同时隐藏第三行的td。 - 重复上述步骤,直到遇到值不相等的一行——此时跳过本次比较,转而将当前行作为新的基准行,继续与下一行比较。
示例
1) tr1 与 tr2 比较,值相等:设置 tr1 的 rowspan 加 1,隐藏 tr2 的 td。

2) tr1 与 tr3 比较,值相等:tr1 的 rowspan 再加 1,隐藏 tr3 的 td。

3) tr1 与 tr4 比较,值不相等。跳过本次比较,转而用 tr4 与 tr5 比较(当前行与下一行)。

2. 多列合并
Grid 的合并可分为单列合并和多列合并。其中多列合并又包含两种模式:
- 逐个列合并:每个列在前一列合并的前提下,可以独立进行合并操作。
- 全部列合并:只有当相邻
tr中指定的所有列内容都相同时,才会执行合并。
2.1 逐个列合并
说明:每个列可基于前面列的合并结果独立判断是否合并。
示例:

2.2 全部列合并
说明:只有相邻 tr 中所有指定列的内容完全一致时,才会进行合并。
示例:

3. 代码与在线演示
3.1 代码
/**
* 合并Grid的数据列
* @param grid {Ext.Grid.Panel} 需要合并的Grid
* @param colIndexArray {Array} 需要合并列的Index(序号)数组;从0开始计数,序号也包含。
* @param isAllSome {Boolean} 是否2个tr的colIndexArray必须完成一样才能进行合并。true:完成一样;false:不完全一样
*/
function mergeGrid(grid, colIndexArray, isAllSome) {
isAllSome = isAllSome == undefined ? true : isAllSome; // 默认为true
// 1.是否含有数据
var gridView = document.getElementById(grid.getView().getId() + '-body');
if (gridView == null) {
return;
}
// 2.获取Grid的所有tr
var trArray = [];
if (grid.layout.type == 'table') { // 若是table部署方式,获取的tr方式如下
trArray = gridView.childNodes;
} else {
trArray = gridView.getElementsByTagName('tr');
}
// 3.进行合并操作
if (isAllSome) { // 3.1 全部列合并:只有相邻tr所指定的td都相同才会进行合并
var lastTr = trArray[0]; // 指向第一行
// 1)遍历grid的tr,从第二个数据行开始
for (var i = 1, trLength = trArray.length; i < trLength; i++) {
var thisTr = trArray[i];
var isPass = true; // 是否验证通过
// 2)遍历需要合并的列
for (var j = 0, colArrayLength = colIndexArray.length; j < colArrayLength; j++) {
var colIndex = colIndexArray[j];
// 3)比较2个td的列是否匹配,若不匹配,就把last指向当前列
if (lastTr.childNodes[colIndex].innerText != thisTr.childNodes[colIndex].innerText) {
lastTr = thisTr;
isPass = false;
break;
}
}
// 4)若colIndexArray验证通过,就把当前行合并到'合并行'
if (isPass) {
for (var j = 0, colArrayLength = colIndexArray.length; j < colArrayLength; j++) {
var colIndex = colIndexArray[j];
// 5)设置合并行的td rowspan属性
if (lastTr.childNodes[colIndex].hasAttribute('rowspan')) {
var rowspan = lastTr.childNodes[colIndex].getAttribute('rowspan') - 0;
rowspan++;
lastTr.childNodes[colIndex].setAttribute('rowspan', rowspan);
} else {
lastTr.childNodes[colIndex].setAttribute('rowspan', '2');
}
// lastTr.childNodes[colIndex].style['text-align'] = 'center';; // 水平居中
lastTr.childNodes[colIndex].style['vertical-align'] = 'middle';; // 纵向居中
thisTr.childNodes[colIndex].style.display = 'none';
}
}
}
} else { // 3.2 逐个列合并:每个列在前面列合并的前提下可分别合并
// 1)遍历列的序号数组
for (var i = 0, colArrayLength = colIndexArray.length; i < colArrayLength; i++) {
var colIndex = colIndexArray[i];
var lastTr = trArray[0]; // 合并tr,默认为第一行数据
// 2)遍历grid的tr,从第二个数据行开始
for (var j = 1, trLength = trArray.length; j < trLength; j++) {
var thisTr = trArray[j];
// 3)2个tr的td内容一样
if (lastTr.childNodes[colIndex].innerText == thisTr.childNodes[colIndex].innerText) {
// 4)若前面的td未合并,后面的td都不进行合并操作
if (i > 0 && thisTr.childNodes[colIndexArray[i - 1]].style.display != 'none') {
lastTr = thisTr;
continue;
} else {
// 5)符合条件合并td
if (lastTr.childNodes[colIndex].hasAttribute('rowspan')) {
var rowspan = lastTr.childNodes[colIndex].getAttribute('rowspan') - 0;
rowspan++;
lastTr.childNodes[colIndex].setAttribute('rowspan', rowspan);
} else {
lastTr.childNodes[colIndex].setAttribute('rowspan', '2');
}
// lastTr.childNodes[colIndex].style['text-align'] = 'center';; // 水平居中
lastTr.childNodes[colIndex].style['vertical-align'] = 'middle';; // 纵向居中
thisTr.childNodes[colIndex].style.display = 'none'; // 当前行隐藏
}
} else {
// 5)2个tr的td内容不一样
lastTr = thisTr;
}
}
}
}
}
3.2 在线演示
为了方便你直观查看合并效果,此处提供了一个可直接运行的示例。由于演示链接已按要求移除,请自行在本地搭建测试环境进行验证。
以上就是 ExtJS 4.2 Grid 单元格合并的完整实现方案,涵盖了原理分析、多列合并策略以及可复用的核心代码。如果你在实际开发中遇到相关问题,可以参考本文档进行调试和适配。
游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。
同类文章
DCloud平台选型指南 适用场景与核心差异详解
DCloud是一个围绕跨平台开发与流应用构建的技术生态,旨在帮助前端开发者使用Web技术开发高性能移动应用。其核心产品包括集成开发环境HBuilderX和基于Vue js的uni-app框架,支持一套代码发布至iOS、Android、Web及多端小程序。相比ReactNative和Flutter,uni-app在多端覆盖和Vue技术栈学习成本上具有优势,适合
DCloud使用教程与常见问题解决方案详解
DCloud提供跨平台应用开发方案,核心为HBuilderX与uni-app框架。开发者使用Vue js语法编写代码,可编译发布至iOS、Android、Web及小程序等多端。流程涵盖项目创建、开发调试与真机预览。常见问题如设备识别、编译失败等可通过检查设置、查看日志与条件编译解决。应用完成后支持云打包生成安装包。
DCloud新手入门教程 从零开始快速掌握开发技巧
DCloud是一个基于Web技术的跨平台应用开发平台,允许开发者使用HTML5等语言编写代码,并编译为iOS、Android及小程序应用,实现“一次编写,多端发布”。开发需使用HBuilderX,基于Vue js进行页面开发,平台提供丰富组件与API,并支持插件市场扩展功能。
DCloud新手入门指南从零开始了解这个开发平台
DCloud是一个移动应用开发平台,旨在帮助前端开发者使用Web技术高效开发性能接近原生的跨平台应用。其核心产品包括HBuilderX开发环境和基于Vue js的uni-app框架,可实现一次开发、多端发布。平台通过完整工具链和插件生态降低开发门槛,适合需要快速迭代、覆盖多端的应用场景。
Zepto实战项目优化技巧与应用场景详解
Zepto js作为轻量级JavaScript库,专为移动端优化,体积仅约10KB。它支持模块化定制,可按需构建以减小体积。使用时需减少DOM操作、善用事件委托,并可混合原生API提升性能。Zepto能融入现代工程流,但需注意其与jQuery的API差异及兼容性限制,适合在移动端性能优先的场景中替代jQuery。
- 热门数据榜
相关攻略
2026-07-10 06:47
2026-07-10 06:47
2026-07-10 06:47
2026-07-10 06:47
2026-07-10 06:47
2026-07-10 06:46
2026-07-10 06:46
2026-07-10 06:46
热门教程
- 游戏攻略
- 安卓教程
- 苹果教程
- 电脑教程

