title: 主从表产品功能说明介绍文档
key words: VisActor,VChart,VTable,VStrory,VMind,VGrammar,VRender,Visualization,Chart,Data,Table,Graph,Gis,LLM
本文作者:
薯片(https://github.com/Violet2314) 广东财经大学
导读
VTable 主从表插件(MasterDetailPlugin)是基于 VisActor VTable 开发的企业级数据可视化组件,专门解决复杂业务场景中的层次化数据展示需求。该插件突破了传统表格的平面化限制,实现了在主表行内嵌入完整子表格的创新交互模式,为用户提供了直观、高效的数据钻取和详情查看体验
核心能力
- 支持在主表行内嵌入完整的子表格,让复杂数据结构一目了然
- 支持静态配置和动态函数配置,满足各种业务场景
- 支持懒加载机制,优化大数据量场景下的性能表现
典型业务场景
| 业务场景 | 主表数据 | 子表数据 |
| 订单管理 | 订单基本信息 | 商品清单、物流详情 |
| 项目管理 | 项目概览 | 任务列表、成员分工 |
| 财务管理 | 汇总数据 | 明细账目、凭证信息 |
| 库存管理 | 产品类别 | SKU详情、库存动态 |
| 客户管理 | 客户基本信息 | 联系记录、交易历史 |
快速上手
获取NPM包
首先,你需要在项目根目录下使用以下命令安装:
*# 使用 npm 安装*
npm install @visactor/vtable @visactor/vtable-plugins
*# 使用 yarn 安装 *
yarn add @visactor/vtable @visactor/vtable-plugins
引入主从表插件
通过 NPM 包引入
import * as VTable from '@visactor/vtable';
import { MasterDetailPlugin } from '@visactor/vtable-plugins';
function generateData(*count*) {
const depts = ['Engineering', 'Marketing', 'Sales', 'HR', 'Finance'];
return Array.from({ length: count }).map((*\_*, *i*) => ({
id: i + 1,
rowNo: i + 1,
name: `姓名 ${i + 1}`,
department: depts[i % depts.length],
score: Math.floor(Math.random() * 100),
amount: Math.floor(Math.random() * 10000) / 100,
children:
i % 4 === 0
? [
{ task: `子任务 A-${i + 1}`, status: 'open' },
{ task: `子任务 B-${i + 1}`, status: 'done' }
]
: undefined
}));
}
const records = generateData(11);
const masterDetailPlugin = new VTablePlugins.MasterDetailPlugin({
id: 'master-detail-static-3',
detailTableOptions: {
columns: [
{ field: 'task', title: '任务名', width: 220 },
{ field: 'status', title: '状态', width: 120 }
],
defaultRowHeight: 30,
defaultHeaderRowHeight: 30,
style: { margin: 12, height: 160 },
theme: VTable.themes.BRIGHT
}
});
const columns = [
{ field: 'id', title: 'ID', width: 70, sort: true },
{ field: 'rowNo', title: '#', width: 60, headerType: 'text', cellType: 'text' },
{ field: 'name', title: '姓名', width: 140, sort: true },
{ field: 'department', title: '部门', width: 140, sort: true },
{ field: 'score', title: '分数', width: 100, sort: true },
{
field: 'amount',
title: '金额',
width: 120,
sort: true,
fieldFormat: (*v*) => {
if (typeof v === 'number' && !isNaN(v)) {
return `$${v.toFixed(2)}`;
}
return v === undefined || v === null ? '' : String(v);
}
}
];
const option = {
container: document.getElementById(CONTAINER\_ID),
columns,
records,
autoFillWidth: true,
hierarchyTextStartAlignment: true,
plugins: [masterDetailPlugin]
};
const tableInstance = new VTable.ListTable(option);
运行后效果:
参数配置
| 参数名称 | 类型 | 默认值 | 功能说明 |
id | string | master-detail-${timestamp} | 插件实例的全局唯一标识符,用于区分多个插件实例 |
enableCheckboxCascade | boolean | true | 是否启用主从表之间的checkbox级联功能,主表中的复选框选择会自动与相应的子表同步 |
detailTableOptions | DetailTableOptions | Function | * |
| 子表配置选项,支持静态对象配置或基于数据的动态配置函数 |
动态配置示例
const masterDetailPlugin = new MasterDetailPlugin({
id: 'employee-detail-plugin',
detailTableOptions: ({ *data*, *bodyRowIndex* }) => {
if (bodyRowIndex === 0) {
return {
columns: [
//......
],
theme: VTable.themes.BRIGHT,
style: {
margin: 20,
height: 300
}
};
}
return {
columns: [
//......
],
theme: VTable.themes.DARK,
style: {
margin: 20,
height: 300
}
};
}
});
主从表插件的主要能力
展开行和渲染子表
当用户点击表格行的展开图标时,系统会在该行下方动态创建一个完整的子表格实例。子表格具备独立的配置、数据源和交互能力,与主表形成层次化的数据展示结构。
当用户点击展开图标时,会触发以下处理链:
用户点击展开图标
↓
EventManager.handleIconClick()
↓
MasterDetailPlugin.expandRow(rowIndex, colIndex)
↓
检查行是否已展开 (isRowExpanded)
↓
获取记录数据 (getRecordByRowIndex)
↓
MasterDetailPlugin.getChildren()
↓
ConfigManager.getDetailConfigForRecord()
↓
updateRowHeightForExpand()
↓
updateContainerHeight()
↓
SubTableManager.renderSubTable()
↓
recalculateAllSubTablePositions(*bodyRowIndex* + 1)
↓
drawUnderlineForRow()
↓
refreshRowIcon()
技术特性
- 独立实例 : 每个子表都是完整的VTable实例,支持所有表格功能
- 动态行高 : 主表行高自动适配子表内容,支持自适应和固定高度
- 位置同步 : 主表滚动时子表位置实时跟随,保持视觉连贯性
- 内存管理 : 收起时自动销毁子表实例,展开时重新创建
生命周期管理
创建阶段: 主表行展开 → 解析配置 → 实例化子表
运行阶段: 位置同步 → 事件处理 → 数据更新
销毁阶段: 行收起 → 清理事件 → 销毁实例 → 回收内存
滚动同步机制
主表滚动时,所有子表会实时跟随滚动,保持视觉上的一体化效果。同时优化了滚动事件的触发机制,并且还有主子表的滚动分离机制,即当鼠标在子表内滚动时并且没有滚动到上下边界的时候,我滚动的是子表的内容,主表是不会滚动的,主表滚动的时候子表是不会滚动的
技术特性
- scrollEventAlwaysTrigger: 自动设置为true,确保边界滚动也能触发事件
- 批量更新: 一次滚动事件批量更新所有子表位置
主从表checkbox联动功能
主从表checkbox联动实现了主表与子表之间选择状态的智能同步。当主表行被选中时,其对应的子表中所有行自动选中;当子表中部分行被选中/取消选中时,主表行的选择状态会相应更新状态。使用参数enableCheckboxCascade来决定是否开启,默认是true
主表checkbox点击 → 检测子表存在 → 遍历子表所有行 → 同步选择状态 → 触发联动回调
子表checkbox点击 → 统计子表选中数量 → 计算主表状态 → 更新主表checkbox → 触发联动回调
技术实现
- 事件监听 : 监听主表和子表的checkbox变化事件
- 状态同步 : 通过内部状态管理器维护选择状态映射关系
- 回调通知 : 选择状态变化时触发相应回调函数,便于业务处理
这种联动机制大大提升了复杂数据结构的操作效率,用户可以通过简单的点击实现批量选择操作。
懒加载功能
当父行记录的 children 字段为 true 时,表示这是一个懒加载节点,需要通过监听 VTable TREE_HIERARCHY_STATE_CHANGE 事件来实现异步数据获取
当用户点击包含懒加载节点的展开图标时,会触发以下调用链:
用户点击展开图标
↓
table.toggleHierarchyState()
↓
触发 TREE\_HIERARCHY\_STATE\_CHANGE 事件
↓
用户事件处理器接收事件参数
↓
tableInstance.setLoadingHierarchyState(col, row) 显示loading图标
↓
异步数据获取
↓
plugin.setRecordChildren(detailData, col, row) 设置数据并展开
↓
渲染子表并完成展开
| 方法 | 说明 | 参数 |
plugin.setLoadingHierarchyState(col, row) | 显示loading图标 | col: 列索引, row: 行索引 |
plugin.setRecordChildren(children, col, row) | 设置子数据并展开 | children: 子数据数组, col: 列索引, row: 行索引 |
用户配置示例
const masterData = [
{ id: 1, name: '订单001', children: true }, *// 懒加载标识*
{ id: 2, name: '订单002', children: [...] } *// 静态数据*
];
const plugin = new MasterDetailPlugin({
detailTableOptions: {
*// 子表配置*
}
});
const tableInstance = new VTable.ListTable(options);
*// 监听主从表层次状态变化事件*
const { MASTER\_DETAIL\_HIERARCHY\_STATE\_CHANGE } = VTable.ListTable.EVENT\_TYPE;
tableInstance.on(MASTER\_DETAIL\_HIERARCHY\_STATE\_CHANGE, async (*args*) => {
if (args.hierarchyState === VTable.TYPES.HierarchyState.expand &&
args.originData?.children === true) {
*// 显示loading状态*
plugin.setLoadingHierarchyState(args.col, args.row);
try {
*// 异步数据获取*
const detailData = await fetchDataFromAPI(args.originData.id);
*// 设置子数据并自动展开*
plugin.setRecordChildren(detailData, args.col, args.row);
} catch (error) {
console.error('Failed to load detail data:', error);
}
}
});
智能缓存机制
- 一次加载 : 数据加载成功后,
children: true自动转换为实际数据数组 - 永久缓存 : 再次点击时识别为静态数据,直接展开无需重新加载
这种设计实现了透明的按需加载,用户只需配置 onLazyLoad 回调,其余状态管理完全由插件自动处理。
小结
VTable 主从表插件是一个正在成长的开源数据展示插件,我们致力于为Web应用提供优秀的层次化数据展示解决方案。
它将复杂的主从数据关系展示能力带到了Web端,同时充分发挥了现代Web技术的交互优势。无论您是要构建订单管理系统、项目管理平台、财务报表系统,还是任何需要主从表功能的Web应用,VTable主从表插件都能为你提供一个良好的选择
在线demo和教程
demo: https://visactor.com/vtable/demo/table-type/list-table-master-detail-table教程: https://visactor.com/vtable/guide/plugin/master-detail
欢迎交流
最后,我们诚挚的欢迎所有对数据可视化感兴趣的朋友参与进来,参与 VisActor 的开源建设:
VTable :VTable 官网、VTable Github(欢迎 Star)
VisActor 官方网站:www.visactor.io/ 或 www.viactor.com
Discord:discord.gg/3wPyxVyH6m
飞书群(外网):打开链接扫码
微信公众号:打开链接扫码
github:github.com/VisActor
