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

news2025/6/7 3:28:39

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.coloradmin.cn/o/2402410.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

『uniapp』把接口的内容下载为txt本地保存 / 读取本地保存的txt文件内容(详细图文注释)

目录 预览效果思路分析downloadTxt 方法readTxt 方法 完整代码总结 欢迎关注 『uniapp』 专栏&#xff0c;持续更新中 欢迎关注 『uniapp』 专栏&#xff0c;持续更新中 预览效果 思路分析 downloadTxt 方法 该方法主要完成两个任务&#xff1a; 下载 txt 文件&#xff1a;通…

【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 时间事件处理部分)

揭秘高效存储模型与数据结构底层实现 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 时间事件&#xff1a;serverCron函数更新服务器时间缓存更新LRU时钟-lruclock更新服务器每秒执行命令次…

【DAY40】训练和测试的规范写法

内容来自浙大疏锦行python打卡训练营 浙大疏锦行 知识点&#xff1a; 彩色和灰度图片测试和训练的规范写法&#xff1a;封装在函数中展平操作&#xff1a;除第一个维度batchsize外全部展平dropout操作&#xff1a;训练阶段随机丢弃神经元&#xff0c;测试阶段eval模式关闭drop…

el-select 实现分页加载,切换也数滚回到顶部,自定义高度

el-select 实现分页加载&#xff0c;切换也数滚回到顶部&#xff0c;自定义高度 1.html <el-form-item label"俱乐部&#xff1a;" prop"club_id" label-width"120px"><el-select :disabled"Boolean(match_id)" style"w…

Langchaine4j 流式输出 (6)

Langchaine4j 流式输出 大模型的流式输出是指大模型在生成文本或其他类型的数据时&#xff0c;不是等到整个生成过程完成后再一次性 返回所有内容&#xff0c;而是生成一部分就立即发送一部分给用户或下游系统&#xff0c;以逐步、逐块的方式返回结果。 这样&#xff0c;用户…

学习经验分享【40】目标检测热力图制作

目标检测热力图在学术论文&#xff08;尤其是计算机视觉、深度学习领域&#xff09;中是重要的可视化分析工具和论证辅助手段&#xff0c;可以给论文加分不少。主要作用一是增强论文的可解释性与说服力&#xff1a;论文中常需解释模型 “如何” 或 “为何” 检测到目标&#xf…

C#里与嵌入式系统W5500网络通讯(3)

有与W5500通讯时,需要使用下面的寄存器: PHYCFGR (W5500 PHY Configuration Register) [R/W] [0x002E] [0b10111XXX] PHYCFGR configures PHY operation mode and resets PHY. In addition, PHYCFGR indicates the status of PHY such as duplex, Speed, Link. 这张表格详细…

用OpenNI2获取奥比中光Astra Pro输出的深度图(win,linux arm64 x64平台)

搞了一个奥比中光Astra Pro&#xff0c;想在windows平台&#xff0c;和linux rk3588 &#xff08;香橙派&#xff0c;ubuntu2404,debian)上获取深度信息&#xff0c;之前的驱动下载已经不好用了,参考如下 Astra 3D相机选型建议 - 知乎https://zhuanlan.zhihu.com/p/594485674 …

Unity VR/MR开发-VR设备与适用场景分析

视频讲解链接&#xff1a;【XR马斯维】VR/MR设备与适用场景分析&#xff1f;【UnityVR/MR开发教程--入门】_游戏热门视频

Linux: network: switch:arp cache更新规则 [chatGPT]

文章目录 介绍概念普通包带有不同的mac,是否更新arp cache?普通包带有相同的mac,是否刷新 aging timeswitch是否会主动学习介绍 关于arp cache在switch侧的行为。有很多问题需要理解。 概念 HP L3 - IP Services Configuration Guide 文档里有写:dynamic arp entry的解说…

Java网络编程API 1

Java中的网络编程API一共有两套&#xff1a;一套是UDP协议使用的API&#xff1b;另一套是TCP协议使用的API。这篇文章我们先来介绍UDP版本的API&#xff0c;并尝试来写一个回显服务器&#xff08;接收到的请求是什么&#xff0c;返回的响应就是什么&#xff09;。 UDP数据报套…

兰亭妙微 | 医疗软件的界面设计能有多专业?

从医疗影像系统到手术机器人控制界面&#xff0c;从便携式病原体检测设备到多平台协同操作系统&#xff0c;兰亭妙微为众多医疗设备研发企业&#xff0c;打造了兼具专业性与可用性的交互界面方案。 我们不仅做设计&#xff0c;更深入理解医疗场景的实际需求&#xff1a; 对精…

前端原生构建交互式进度步骤组件(Progress Steps)

在现代网页设计中&#xff0c;进度步骤&#xff08;Progress Steps&#xff09; 是一种常见的 UI 模式&#xff0c;常用于引导用户完成注册流程、多步表单、教程或任何需要分步骤操作的场景。本文将带你从零开始构建一个美观且功能完整的 “进度步骤”组件&#xff0c;并详细讲…

【基于阿里云搭建数据仓库(离线)】Data Studio创建资源与函数

Data Studio支持在您的数据分析代码中引用自定义的资源和函数&#xff08;支持MaxCompute、EMR、CDH、Flink&#xff09;&#xff0c;您需要先创建或上传资源、函数至目标工作空间&#xff0c;上传后才可在该工作空间的任务中使用。您可参考本文了解如何使用DataWorks可视化方式…

web3-以太坊智能合约基础(理解智能合约Solidity)

以太坊智能合约基础&#xff08;理解智能合约/Solidity&#xff09; 无需编程经验&#xff0c;也可以帮助你了解Solidity独特的部分&#xff1b;如果本身就有相应的编程经验如java&#xff0c;python等那么学起来也会非常的轻松 一、Solidity和EVM字节码 实际上以太坊链上储存…

【C++项目】负载均衡在线OJ系统-2

文章目录 oj_server模块编写oj_server框架的搭建-oj_server/oj_server.cpp 路由框架 oj_model模块编写题目信息设置v1.文件版本-common/util.hpp boost库spilt函数的使用-oj_server/oj_model_file.hpp 文件版本model编写v2.mysql数据库版本1.mysql创建授权用户、建库建表录入操…

GC1809:高性能24bit/192kHz音频接收芯片解析

1. 芯片概述 GC1809 是数字音频接收芯片&#xff0c;支持IEC60958、S/PDIF、AES3等协议&#xff0c;集成8选1输入切换、低抖动时钟恢复和24bit DAC&#xff0c;适用于家庭影院、汽车音响等高保真场景。 核心特性 高精度&#xff1a;24bit分辨率&#xff0c;动态范围105dB&…

2025年06月05日Github流行趋势

项目名称&#xff1a;onlook 项目地址url&#xff1a;https://github.com/onlook-dev/onlook项目语言&#xff1a;TypeScript历史star数&#xff1a;16165今日star数&#xff1a;1757项目维护者&#xff1a;Kitenite, drfarrell, spartan-vutrannguyen, apps/devin-ai-integrat…

基于BI PaaS架构的衡石HENGSHI SENSE平台技术解析:重塑企业级数据分析基座

在数据驱动决策的时代&#xff0c;传统BI工具日益显露出扩展性弱、灵活性差、资源利用率低等痛点。衡石科技推出的HENGSHI SENSE平台&#xff0c;创新性地采用BI PaaS&#xff08;平台即服务&#xff09;架构&#xff0c;为企业构建了一个强大、开放、可扩展的数据分析基础设施…

【R语言编程绘图-plotly】

安装与加载 在R中使用plotly库前需要安装并加载。安装可以通过CRAN进行&#xff0c;使用install.packages()函数。加载库使用library()函数。 install.packages("plotly") library(plotly)测试库文件安装情况 # 安装并加载必要的包 if (!requireNamespace("p…