当前位置: 首页 > article >正文

Web前端之原生表格动态复杂合并行、Vue

MENU

  • 效果
  • 公共数据
  • 纯原生
    • Style
    • JavaScript
  • vue+原生table


效果

原生的JavaScript+原生table
原生JavaScript


null


公共数据

const list = [{id: "a1",title: "第一列",list: [{id: "a11",parentId: "a1",title: "第二列",list: [{ id: "a111", parentId: "a11", title: "第三列第一行" },{ id: "a112", parentId: "a11", title: "第三列第二行" },{ id: "a113", parentId: "a11", title: "第三列第三行" },],},],},{id: "a2",title: "第一列",list: [{id: "a21",parentId: "a2",title: "第二列",list: [{ id: "a211", parentId: "a21", title: "第三列第一行" },{ id: "a212", parentId: "a21", title: "第三列第二行" },{ id: "a213", parentId: "a21", title: "第三列第三行" },],},{id: "a22",parentId: "a2",title: "第二列",list: [{ id: "a221", parentId: "a22", title: "第三列第一行" },{ id: "a222", parentId: "a22", title: "第三列第二行" },],},],},{id: "a3",title: "第一列",list: [{id: "a31",parentId: "a3",title: "第二列",list: [{ id: "a311", parentId: "a31", title: "第三列第一行" }],},],},
];

纯原生

Style

body {margin: 0px;display: flex;justify-content: center;
}
.merged-table {border-collapse: collapse;margin: 20px;width: 95%;
}
.merged-table td,
.merged-table th {border: 1px solid #ddd;padding: 8px;text-align: left;
}
.merged-table th {background-color: #f2f2f2;font-weight: bold;
}
.no-data {text-align: center;color: #999;padding: 20px;
}

JavaScript

function createMergedTable(data, container, options = {}) {// 清除容器原有内容container.innerHTML = "";// 合并配置const config = {classNames: ["merged-table", ...(options.classNames || [])],headers: options.headers || null,emptyText: options.emptyText || "暂无数据",};// 计算行合并数function computeRowspan(node) {if (!node.list || node.list.length === 0) {node.rowspan = 1;return 1;}let total = 0;for (const child of node.list) total += computeRowspan(child);node.rowspan = total;return total;}// 收集所有叶子节点路径function collectLeaves(node, chain = [], result = []) {const newChain = [...chain, node];if (!node.list || node.list.length === 0) {result.push(newChain);return result;}for (const child of node.list) collectLeaves(child, newChain, result);return result;}// 创建表头function createHeader(table, depth) {const thead = document.createElement("thead");const tr = document.createElement("tr");const headers =config.headers ||Array.from({ length: depth }, (_, i) => `层级${i + 1}`).concat(["明细项",]);headers.forEach((text) => {const th = document.createElement("th");th.textContent = text;tr.appendChild(th);});thead.appendChild(tr);table.appendChild(thead);}// 创建表格主体function createTableBody(leaves) {const table = document.createElement("table");table.className = config.classNames.join(" ");// 空数据处理if (leaves.length === 0) {const tr = document.createElement("tr");const td = document.createElement("td");td.className = "no-data";td.colSpan = config.headers?.length || 3;td.textContent = config.emptyText;tr.appendChild(td);table.appendChild(tr);return table;}// 确定列数const columnCount = leaves[0].length;const mergeColumnCount = Math.max(0, columnCount - 1);// 创建表头createHeader(table, mergeColumnCount);// 初始化列跟踪器const trackers = Array(mergeColumnCount).fill().map(() => ({}));// 创建数据行const tbody = document.createElement("tbody");leaves.forEach((chain) => {const tr = document.createElement("tr");// 处理需要合并的列for (let i = 0; i < mergeColumnCount; i++) {const node = chain[i];if (!trackers[i][node.id]) {const td = document.createElement("td");td.textContent = node.title;td.rowSpan = node.rowspan;tr.appendChild(td);trackers[i][node.id] = node.rowspan - 1;} else {trackers[i][node.id]--;if (trackers[i][node.id] === 0) delete trackers[i][node.id];}}// 添加最后一列(不合并)const lastTd = document.createElement("td");lastTd.textContent = chain[chain.length - 1].title;tr.appendChild(lastTd);tbody.appendChild(tr);});table.appendChild(tbody);return table;}// 执行主流程try {// 预处理数据data.forEach((node) => computeRowspan(node));const leaves = data.flatMap((node) => collectLeaves(node));// 生成表格const table = createTableBody(leaves);container.appendChild(table);} catch (error) {console.error("表格生成失败:", error);container.innerHTML = `<div class="error">表格生成失败: ${error.message}</div>`;}
}// 使用示例
createMergedTable(list, document.body, {headers: ["一级分类", "二级分类", "具体项目"],classNames: ["custom-table"],emptyText: "没有找到数据",
});

vue+原生table

敬请期待…

http://www.lryc.cn/news/2402410.html

相关文章:

  • 『uniapp』把接口的内容下载为txt本地保存 / 读取本地保存的txt文件内容(详细图文注释)
  • C/C++ 面试复习笔记(2)
  • 宝马集团推进数字化转型:强化生产物流与财务流程,全面引入SAP现代架构
  • 【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 时间事件处理部分)
  • 【DAY40】训练和测试的规范写法
  • C语言 标准I/O函数全面指南
  • el-select 实现分页加载,切换也数滚回到顶部,自定义高度
  • Langchaine4j 流式输出 (6)
  • Jenkins:自动化流水线的基石,开启 DevOps 新时代
  • 学习经验分享【40】目标检测热力图制作
  • C#里与嵌入式系统W5500网络通讯(3)
  • 用OpenNI2获取奥比中光Astra Pro输出的深度图(win,linux arm64 x64平台)
  • Unity VR/MR开发-VR设备与适用场景分析
  • Linux: network: switch:arp cache更新规则 [chatGPT]
  • Java网络编程API 1
  • Android协程学习
  • Angular报错:cann‘t bind to ngClass since it is‘t a known property of div
  • uniapp+vue3实现CK通信协议(基于jjc-tcpTools)
  • Python爬虫实战:研究urlparse库相关技术
  • 解锁FastAPI与MongoDB聚合管道的性能奥秘
  • 软件工程方法论:在确定性与不确定性的永恒之舞中寻找平衡
  • Unity中的MonoSingleton<T>与Singleton<T>
  • 怎么通过 jvmti 去 hook java 层函数
  • 兰亭妙微 | 医疗软件的界面设计能有多专业?
  • 前端原生构建交互式进度步骤组件(Progress Steps)
  • 如何给windos11 扩大C盘容量
  • 【基于阿里云搭建数据仓库(离线)】Data Studio创建资源与函数
  • Linux_T(Sticky Bit)粘滞位详解
  • web3-以太坊智能合约基础(理解智能合约Solidity)
  • 高敏感应用如何保护自身不被逆向?iOS 安全加固策略与工具组合实战(含 Ipa Guard 等)