1. 理解jEasyUI子网格的核心概念
在Web开发中,数据表格是最常用的UI组件之一,而jEasyUI的数据网格(datagrid)组件提供了丰富的功能来展示结构化数据。子网格(SubGrid)是一种特殊的数据展示方式,它允许我们在主网格的每一行下方展开一个附属的详细视图,这个视图可以包含额外的关联数据或者操作界面。
1.1 为什么需要子网格设计
传统的数据展示方式存在几个明显痛点:
- 关联数据需要跳转页面查看,破坏用户体验连续性
- 弹出窗口会遮挡主表格内容,且需要额外关闭操作
- 表格列数过多导致横向滚动,降低数据可读性
子网格设计完美解决了这些问题:
- 保持上下文关联:子网格与主行数据直接对应
- 无干扰展开:只在当前行下方扩展,不影响其他数据浏览
- 按需加载:仅在用户点击展开时获取数据,优化性能
1.2 jEasyUI子网格的技术实现原理
jEasyUI通过detailview扩展实现子网格功能,其核心机制包含三个部分:
- 视图容器:通过detailFormatter定义子网格的HTML容器
javascript复制detailFormatter: function(index,row){
return '<div style="padding:2px"><table class="ddv"></table></div>';
}
- 动态加载:在onExpandRow事件中初始化子网格
javascript复制onExpandRow: function(index,row){
var ddv = $(this).datagrid('getRowDetail',index).find('table.ddv');
ddv.datagrid({
// 子网格配置
});
}
- 高度同步:使用fixDetailRowHeight方法保持主从网格的视觉一致性
javascript复制$('#dg').datagrid('fixDetailRowHeight',index);
2. 完整实现jEasyUI子网格
2.1 环境准备与基础配置
首先确保项目中已引入必要的资源文件:
html复制<!-- jEasyUI核心库 -->
<link rel="stylesheet" type="text/css" href="jeasyui/themes/default/easyui.css">
<script type="text/javascript" src="jeasyui/jquery.min.js"></script>
<script type="text/javascript" src="jeasyui/jquery.easyui.min.js"></script>
<!-- 子网格扩展 -->
<script type="text/javascript" src="jeasyui/datagrid-detailview.js"></script>
主网格的基础HTML结构:
html复制<table id="mainGrid" style="width:800px;height:400px"
url="get_main_data.php"
title="产品主数据"
singleSelect="true"
fitColumns="true">
<thead>
<tr>
<th field="productId" width="100">产品ID</th>
<th field="productName" width="200">产品名称</th>
<th field="category" width="150">分类</th>
<th field="price" width="80" align="right">价格</th>
</tr>
</thead>
</table>
2.2 主网格的JavaScript初始化
完整的子网格初始化代码应包含以下关键配置:
javascript复制$('#mainGrid').datagrid({
view: detailview,
detailFormatter: function(index, row){
return '<div class="detail-container"><table class="subgrid"></table></div>';
},
onExpandRow: function(index, row){
var subgrid = $(this).datagrid('getRowDetail', index).find('table.subgrid');
subgrid.datagrid({
url: 'get_sub_data.php?productId=' + row.productId,
fitColumns: true,
singleSelect: true,
columns: [[
{field: 'orderId', title: '订单号', width: 120},
{field: 'customer', title: '客户', width: 150},
{field: 'quantity', title: '数量', width: 80, align: 'right'},
{field: 'orderDate', title: '日期', width: 100}
]],
onResize: function(){
$('#mainGrid').datagrid('fixDetailRowHeight', index);
},
onLoadSuccess: function(){
setTimeout(function(){
$('#mainGrid').datagrid('fixDetailRowHeight', index);
}, 0);
}
});
}
});
2.3 服务器端数据接口实现
主数据接口(get_main_data.php)示例:
php复制<?php
header('Content-Type: application/json');
$conn = new mysqli("localhost", "user", "password", "dbname");
$result = $conn->query("SELECT * FROM products");
$data = array();
while($row = $result->fetch_assoc()){
$data[] = $row;
}
echo json_encode($data);
?>
子数据接口(get_sub_data.php)示例:
php复制<?php
header('Content-Type: application/json');
$productId = $_GET['productId'];
$conn = new mysqli("localhost", "user", "password", "dbname");
$stmt = $conn->prepare("SELECT * FROM orders WHERE product_id = ?");
$stmt->bind_param("s", $productId);
$stmt->execute();
$result = $stmt->get_result();
$data = array();
while($row = $result->fetch_assoc()){
$data[] = $row;
}
echo json_encode($data);
?>
3. 高级功能与性能优化
3.1 子网格的多级嵌套实现
jEasyUI支持多级子网格嵌套,只需在子网格的onExpandRow中再次初始化下级网格:
javascript复制onExpandRow: function(index, row){
var subgrid = $(this).datagrid('getRowDetail', index).find('table.subgrid');
subgrid.datagrid({
// ...基础配置...
view: detailview,
detailFormatter: function(index, row){
return '<div class="subdetail"><table class="level3-grid"></table></div>';
},
onExpandRow: function(index, row){
var level3 = $(this).datagrid('getRowDetail', index)
.find('table.level3-grid');
level3.datagrid({
// 三级网格配置
});
}
});
}
3.2 大数据量优化策略
当处理大量数据时,可采用以下优化方案:
- 分页加载:
javascript复制subgrid.datagrid({
pagination: true,
pageSize: 10,
pageList: [10,20,50]
});
- 虚拟滚动:
javascript复制$('#mainGrid').datagrid({
view: scrollview,
scrollbarSize: 0
});
- 延迟渲染:
javascript复制onBeforeLoad: function(param){
if(param.page == undefined){
param.page = 1;
param.rows = 50; // 初始加载50条
}
}
3.3 自定义子网格内容
子网格不仅限于表格,可以包含任意HTML内容:
javascript复制detailFormatter: function(index, row){
return `
<div class="custom-detail">
<div class="product-image">
<img src="${row.imageUrl}" width="120">
</div>
<div class="product-desc">
<h4>${row.productName}</h4>
<p>${row.description}</p>
<button onclick="addToCart('${row.productId}')">加入购物车</button>
</div>
</div>`;
}
4. 实战问题排查与解决方案
4.1 常见问题排查清单
- 子网格不显示:
- 检查是否引用了datagrid-detailview.js
- 确认view: detailview配置正确
- 查看控制台是否有JavaScript错误
- 高度计算异常:
- 确保调用了fixDetailRowHeight
- 检查CSS是否影响了高度计算
- 尝试在setTimeout中调用fix方法
- 数据加载失败:
- 检查URL是否正确拼接
- 验证服务器端返回的JSON格式
- 使用开发者工具查看网络请求
4.2 样式定制技巧
自定义子网格样式示例:
css复制/* 主网格行样式 */
.datagrid-row-expanded {
background-color: #f5f5f5;
}
/* 子网格容器 */
.detail-container {
padding: 10px;
border-top: 1px solid #ddd;
background: #fff;
}
/* 子网格表头 */
.subgrid .datagrid-header {
background: #e6e6e6;
}
/* 展开图标 */
.datagrid-row-expander {
background-position: center center;
}
4.3 移动端适配方案
针对移动设备的优化调整:
javascript复制$('#mainGrid').datagrid({
// 响应式配置
width: '100%',
height: 'auto',
singleSelect: true,
nowrap: false, // 允许换行
columns: [[
{field: 'productName', title: '产品', width: 120},
{field: 'price', title: '价格', width: 60}
]],
onResize: function(){
$(this).datagrid('resize');
}
});
// 媒体查询调整
$(window).on('resize', function(){
if($(window).width() < 768){
$('#mainGrid').datagrid('resize', {
width: '100%',
height: 'auto'
});
}
});
在实际项目中,我发现子网格的初始化时机对性能影响很大。特别是在移动设备上,建议采用懒加载策略:只在用户首次点击展开时初始化子网格,而不是在页面加载时就预初始化所有子网格容器。这可以显著提升页面响应速度,特别是在数据量较大的情况下。
