当前位置: 首页
前端开发
ExtJS 4.2 Grid单元格合并实现技巧

ExtJS 4.2 Grid单元格合并实现技巧

热心网友 时间:2026-06-12
转载

ExtJS4 2Grid单元格合并通过操作tr和td的rowspan属性实现,重复行隐藏。多列合并分逐个列与全部列两种方式,提供mergeGrid函数代码,支持指定列索引及是否全部列相同才合并。

ExtJS 4.2 的 Grid 组件默认不具备单元格合并功能,需要开发者手动实现。本文将深入拆解实现原理与核心代码,帮助你快速掌握合并技巧,避免常见问题。

目录

1. 原理
2. 多列合并
3. 代码与在线演示

1. 原理

1.1 HTML 代码分析

首先创建一个基础的 Grid 组件,然后观察其生成的 HTML 结构。

\

\

通过分析生成的 HTML 可以看出,Grid 组件主要分为 grid-headergrid-body 两大区域(若启用了工具栏或分页栏,则会额外拥有独立的区域)。

在 grid-body 内部,包含若干 tr 元素,每个 tr 对应 Grid 中的一行数据;每个 tr 中又包含多个 td,每个 td 就是一个具体的单元格。

\

1.2 原理

步骤说明

整个合并操作的核心都围绕 tr 元素展开,具体流程如下:

  1. 比较第一行 tr 与第二行 tr 的某个 td 的值,若两行的内容相等:将第一行 tr 的该 tdrowspan 属性值增加 1,并将第二行 tr 的对应 td 隐藏。
  2. 接着拿第一行 tr 与第三行 tr 比较,若值仍相等:第一行的 rowspan 再增加 1,同时隐藏第三行的 td
  3. 重复上述步骤,直到遇到值不相等的一行——此时跳过本次比较,转而将当前行作为新的基准行,继续与下一行比较。

示例

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 单元格合并的完整实现方案,涵盖了原理分析、多列合并策略以及可复用的核心代码。如果你在实际开发中遇到相关问题,可以参考本文档进行调试和适配。

来源:https://www.jb51.net/article/94597.htm

游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。

同类文章
更多
DCloud平台选型指南 适用场景与核心差异详解

DCloud平台选型指南 适用场景与核心差异详解

DCloud是一个围绕跨平台开发与流应用构建的技术生态,旨在帮助前端开发者使用Web技术开发高性能移动应用。其核心产品包括集成开发环境HBuilderX和基于Vue js的uni-app框架,支持一套代码发布至iOS、Android、Web及多端小程序。相比ReactNative和Flutter,uni-app在多端覆盖和Vue技术栈学习成本上具有优势,适合

时间:2026-07-10 06:47
DCloud使用教程与常见问题解决方案详解

DCloud使用教程与常见问题解决方案详解

DCloud提供跨平台应用开发方案,核心为HBuilderX与uni-app框架。开发者使用Vue js语法编写代码,可编译发布至iOS、Android、Web及小程序等多端。流程涵盖项目创建、开发调试与真机预览。常见问题如设备识别、编译失败等可通过检查设置、查看日志与条件编译解决。应用完成后支持云打包生成安装包。

时间:2026-07-10 06:47
DCloud新手入门教程 从零开始快速掌握开发技巧

DCloud新手入门教程 从零开始快速掌握开发技巧

DCloud是一个基于Web技术的跨平台应用开发平台,允许开发者使用HTML5等语言编写代码,并编译为iOS、Android及小程序应用,实现“一次编写,多端发布”。开发需使用HBuilderX,基于Vue js进行页面开发,平台提供丰富组件与API,并支持插件市场扩展功能。

时间:2026-07-10 06:47
DCloud新手入门指南从零开始了解这个开发平台

DCloud新手入门指南从零开始了解这个开发平台

DCloud是一个移动应用开发平台,旨在帮助前端开发者使用Web技术高效开发性能接近原生的跨平台应用。其核心产品包括HBuilderX开发环境和基于Vue js的uni-app框架,可实现一次开发、多端发布。平台通过完整工具链和插件生态降低开发门槛,适合需要快速迭代、覆盖多端的应用场景。

时间:2026-07-10 06:47
Zepto实战项目优化技巧与应用场景详解

Zepto实战项目优化技巧与应用场景详解

Zepto js作为轻量级JavaScript库,专为移动端优化,体积仅约10KB。它支持模块化定制,可按需构建以减小体积。使用时需减少DOM操作、善用事件委托,并可混合原生API提升性能。Zepto能融入现代工程流,但需注意其与jQuery的API差异及兼容性限制,适合在移动端性能优先的场景中替代jQuery。

时间:2026-07-10 06:47
热门专题
更多
刀塔传奇破解版无限钻石下载大全 刀塔传奇破解版无限钻石下载大全
洛克王国正式正版手游下载安装大全 洛克王国正式正版手游下载安装大全
思美人手游下载专区 思美人手游下载专区
好玩的阿拉德之怒游戏下载合集 好玩的阿拉德之怒游戏下载合集
不思议迷宫手游下载合集 不思议迷宫手游下载合集
百宝袋汉化组游戏最新合集 百宝袋汉化组游戏最新合集
jsk游戏合集30款游戏大全 jsk游戏合集30款游戏大全
宾果消消消原版下载大全 宾果消消消原版下载大全
  • 热门数据榜