在vue中通过js动态绘制table,并且合并连续相同内容的行,支持点击编辑单元格内容
首先是vue代码
<template><div id="body-container"style="position: absolute"><div class="box-container"><div class="lsb-table-box" ><div class="table-container" id="lsb-table"></div></div></div></div></template>
然后是js方法
/*** 渲染表格*/
function tableRenderCs() {const data=[{"one": "测试1","two": "测试2","three": "测试3","four": "测试4","five": "测试5","six": "测试6","seven": "测试7","eight": "测试8","nine": "测试9"},{"one": "测试1","two": "测试2","three": "测试3","four": "测试4","five": "测试5","six": "测试6","seven": "测试7","eight": "测试8","nine": "测试9"},{"one": "测试1","two": "测试2","three": "测试3","four": "测试4","five": "测试5","six": "测试6","seven": "测试7","eight": "测试8","nine": "测试9"}]let html = '<table class="table-wj JZ-A" border="1" cellspacing="0">' +'<thead>' +'<tr>' +'<th rowspan="2" colspan="3">第一列</th>' +'<th rowspan="2" colspan="1" style="width: 50px;">第二列</th>' +'<th rowspan="2" colspan="1" style="width: 100px;">第三列</th>' +'<th rowspan="2" colspan="1" style="width: 50px;">第四列</th>' +'<th rowspan="2" colspan="1" style="width: 80px;">第五列</th>' +'<th rowspan="1" colspan="3">第六列</th>' +'</tr>' +'<tr>' +'<th colspan="1" style="width: 50px;">第六列的第一列</th>' +'<th colspan="1" style="width: 90px;">第六列的第二列</th>' +'</tr>' +'</thead>' +'<tbody>';for (let i = 0; i < data.length; i++) {const item = data[i];html +=`<tr>` +`<td>${item.one}</td>` +`<td>${item.two}</td>` +`<td>${item.three}</td>` +`<td>${item.four}</td>` +`<td>${item.five}</td>` +`<td>${item.six}</td>` +`<td>${item.seven}</td>` +`<td>${item.eight}</td>` +`<td>${item.nine}</td>` +`</tr>`;}html += '</tbody></table>';let _$ = $(".lsb-table-box .table-container");_$.append(html);//存储列名对应的字段值,方便后面计算let rowName = {'0': 'one','1': 'two','2': 'three','3': 'four','4': 'five','5': 'six','6': 'seven','7': 'eight','8': 'nine',}editInput(_$, data, "two", rowName);mergeColumns(); //调用动态合并行的方法
}/*** 执行合并逻辑*/
function mergeColumns() {let $table = $('table.table-wj');let $rows = $table.find('tbody tr');const numCols = $rows.eq(0).find('td').length;//考虑全部列//const numCols = Math.min(3, $rows.eq(0).find('td').length); // 仅考虑前三列// 遍历每列for (let col = 1; col <= numCols; col++) {let $currentColumn = $table.find(`td:nth-child(${col})`);let prevContent = null;let rowspan = 1;for (let i = 0; i < $currentColumn.length; i++) {let $currentCell = $($currentColumn[i]);let currentContent = $currentCell.text();if (currentContent === prevContent) {rowspan++;$currentCell.addClass('hidden');} else {if (rowspan > 1) {$currentColumn.eq(i - rowspan).attr('rowspan', rowspan);}prevContent = currentContent;rowspan = 1;}}if (rowspan > 1) {$currentColumn.eq($currentColumn.length - rowspan).attr('rowspan', rowspan);}}// 清除被隐藏的单元格$table.find('.hidden').remove();
}
const numCols这里给出了两种合并表格的逻辑,第一个是只会对前三列执行合并逻辑,而第二个会对所有列执行合并逻辑。下面是两种逻辑的合并效果图。


接下来是使单元格可以被编辑,并且获取到编辑后的值,以及单元格位置
在上面的方法中调用即可editInput(_$, data, "two", rowName); //这里的four是上面 `<td>${item.four}</td>` 对应的字段名,也就是列名mergeColumns(); //这里一定要注意先调用editInput方法再调用mergeColumns,不然获取编辑单元格的列索引会有问题/*** 设置单元格可编辑* @param _$ 表对象* @param data 表数据* @param fieldName 编辑后要获取的值对应的列名* @param rowName 列的索引与数据库字段相对应的集合*/
function editInput(_$, data, fieldName, rowName) {// 获取所有表格单元格let cells = _$.find('td');// 为每个单元格添加点击事件cells.each(function (index) {let column = $(this).index();let row = $(this).closest('tr').index();let columnName = Object.keys(data[0])[column]; // 获取对应列的字段名$(this).data('columnName', columnName); // 存储列名为数据属性$(this).on('mousedown', function (event) {// 如果是鼠标右键点击,不进行操作if (event.which === 3) return;let $input = $(this).find('input'); // 检查单元格内是否已有输入框if ($input.length === 0) { // 如果没有输入框,则进行以下操作let currentValue = $(this).text();// 创建一个输入框元素,并将当前单元格内容设置为其值$input = $('<input type="text">');$input.val(currentValue);// 设置输入框的样式$input.css({'background-color': 'transparent', // 设置背景色为透明'color': 'white', // 设置文字颜色为白色'border': 'none', // 移除边框'outline': 'none', // 移除外边框});// 清空单元格并将输入框添加到单元格中$(this).empty().append($input);// 焦点定位到输入框$input.focus();// 阻止默认行为event.preventDefault();// 处理输入框失去焦点事件$input.on('blur', function () {let newValue = $input.val();let valueName = rowName[column]; // 获取列索引对应的字段名称let columnValue = data[row][fieldName]; // 获取对应字段的值console.log('编辑后的内容:', newValue);console.log('所在单元格位置:', '行:', row, '列:', column);console.log('所在列字段名:', valueName);console.log(fieldName + '列的值:', columnValue);console.log(`更改了${fieldName}为${columnValue}的字段${valueName}的值为${newValue}`)$(this).parent('td').text(newValue);});}});});
}
实现效果如下,同时还获取了当前单元格所在行里面指定的某一列的数据内容(比如可以获取当前行的id,以此来给后端修改数据库中的数据),注意行是从表头下面开始的,行和列的下标都是从0开始

相关文章:
在vue中通过js动态绘制table,并且合并连续相同内容的行,支持点击编辑单元格内容
首先是vue代码 <template><div id"body-container"style"position: absolute"><div class"box-container"><div class"lsb-table-box" ><div class"table-container" id"lsb-table"&…...
输电线路定位:精确导航,确保电力传输安全
在现代社会中,电力作为生活的基石,其安全稳定运行至关重要。而输电线路作为电力传输的重要通道,其故障定位和修复显得尤为重要。恒峰智慧科技将为您介绍一种采用分布式行波测量技术的输电线路定位方法,以提高故障定位精度…...
ZKP Commitment (1)
MIT IAP 2023 Modern Zero Knowledge Cryptography课程笔记 Lecture 5: Commitment 1 (Ying Tong Lai) Overview: Modern SNARK IOP: Interactive Oracle ProofCommitment SchemeIOP “compiled by” the commitment scheme to get a non-interactive proofAn IOP is “inform…...
【难点】【LRU】146.LRU缓存
题目 法1:基于Java的LinkedHashMap 必须掌握法1。参考链接 关于LinkedHashMap的介绍 class LRUCache {int cap;LinkedHashMap<Integer, Integer> cache new LinkedHashMap<>();public LRUCache(int capacity) { this.cap capacity;}public int get…...
基于YOLOv8深度学习的吸烟/抽烟行为检测系统【python源码+Pyqt5界面+数据集+训练代码】目标检测、深度学习实战
《博主简介》 小伙伴们好,我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源,可关注公-仲-hao:【阿旭算法与机器学习】,共同学习交流~ 👍感谢小伙伴们点赞、关注! 《------往期经典推…...
菜鸟学习日记(python)——匿名函数
Python 使用 lambda 来创建匿名函数。 lambda 函数是一种小型、匿名的内联函数,它可以具有任意数量的参数,但只能有一个表达式。 匿名函数的一般格式如下: lambda 参数列表:表达式 表达式用于计算并返回函数结果 lambda 函数通常用于编写…...
CompleteFuture与Future的比较
CompleteFuture的介绍CompleteFuture的特点CompleteFuture的应用场景CompletableFuture的优缺点Future的介绍Future的特点Future的应用场景Future的优缺点CompletableFuture和Future的区别CompletableFuture和Future的关联关系CompletableFuture和Future的使用示例CompletableF…...
数据分享 I 全国市级商品房屋销售数据,shp/excel格式,2005-2020年数据
基本信息. 数据名称: 全国市级商品房屋销售数据 数据格式: Shp、excel 数据时间: 2005-2020年 数据几何类型: 面 数据坐标系: WGS84坐标系 数据来源:网络公开数据 数据字段: 序号字段名称字段说明1spxse商品房销售额(亿元…...
面试题总结(十一)【C++】【华清远见西安中心】
C和C的区别有哪些? C 和 C 是两种不同的编程语言,它们有以下一些区别: 1. 语言起源和发展:C 语言是由贝尔实验室的 Dennis Ritchie 在 1972 年开发的,主要用于系统编程和底层开发;而 C 语言是在 C 语言的基…...
c++_01_名字空间_复合类型_缺省参数_哑元函数
0 前言 C和C一样,都属于编译型语言 C和C一样,都属于强类型语言 C对C完全兼容,并提供更多面向对象的特性:语言风格更加简洁,类型检查更加严格 1 名字空间 namespace WHY?划分更精细的逻辑单元(逻辑空间)&…...
前端常见面试题之html和css篇
文章目录 一、html1. 如何理解html语义化2. 说说块级元素和内联元素的区别 二、css1. 盒模型的宽度offsetWidth如何计算2. box-sizing:border-box有什么用3. margin的纵向重叠问题4. 谈谈你对BFC的理解和应用5. 清除浮动有哪些方式6. 使用flex布局实现骰子37.position的absolut…...
使用libaom处理av1编码教程
使用libaom处理av1编码教程 文章目录 使用libaom处理av1编码教程一. av1 是什么二. av1 用处三. libaom 是什么四. libaom 安装五. libaom 安装完成六. 解码av1 一. av1 是什么 AV1(AOMedia Video 1)是一种 开源视频编码格式 。它由开放媒体联盟 (AOM) …...
面试题总结(十)【数据库】【华清远见西安中心】
数据库的分类有哪些? 数据库可以按照不同的标准进行分类,以下是一些常见的数据库分类方式: 1. 关系型数据库(Relational Database):关系型数据库采用表格的形式来组织数据,数据之间通过键值关联…...
计算机网络:物理层(三种数据交换方式)
今天又学到一个知识,加油! 目录 前言 一、电路交换 二、报文交换 三、分组交换 1、数据报方式 2、虚电路方式 3、比较 总结 前言 为什么要进行数据交换? 一、电路交换 电路交换原理:在数据传输期间,源结点与…...
ubuntu18.04 64 位安装笔记——备赛笔记——2024全国职业院校技能大赛“大数据应用开发”赛项——任务2:离线数据处理
进入VirtuakBox官网,网址链接:Oracle VM VirtualBoxhttps://www.virtualbox.org/ 网页连接:Ubuntu Virtual Machine Images for VirtualBox and VMwarehttps://www.osboxes.org/ubuntu/ 将下发的ds_db01.sql数据库文件放置mysql中 12、编写S…...
Nvidia 驱动安装不完整记录
Nvidia 驱动安装不完整记录 安装 epel, sudo dnf install -y https://dl.fedoraproject.org/pub/epel/epel-releaselatest-8.noarch.rpm安装 gcc-toolset-11-gcc, dnf install gcc-toolset-11-gcc修改 gcc,make,as 为 gcc-tools…...
龙芯loongarch64服务器编译安装gcc-8.3.0
前言 当前电脑的gcc版本为8.3.0,但是在编译其他依赖包的时候,出现各种奇怪的问题,会莫名其妙的中断编译。本地文章讲解如何自编译安装gcc,替换系统自带的gcc。 环境准备 下载页面:龙芯开源社区网站 - LoongArch GCC 8.3 交叉工具链 - 源码下载源码包名称如:loongson-gnu…...
宏基因组学Metagenome-磷循环Pcycle功能基因分析-从分析过程到代码及结果演示-超详细保姆级流程
大背景介绍 生信分析,凡事先看论文,有了论文就有了参考,后续分析就有底了,直接上硬菜开干: PCycDB: a comprehensive and accurate database for fast analysis of phosphorus cycling genes - PubMed 数据库及部分分析代码github库: GitHub - ZengJiaxiong/Phospho…...
element plus 日期范围 自定义内容
问题: 按照官网上的自定义内容示例,修改日期选择器没有问题,如果修改日期范围选择器,修改后会丢失日期范围选择时的样式。 解决: 从F12中不难看出日期范围的选择样式来自于.el-date-table-cell 而示例中写的是.cell&…...
[23] GaussianAvatars: Photorealistic Head Avatars with Rigged 3D Gaussians
[paper | proj] 给定FLAME,基于每个三角面片中心初始化一个3D Gaussian(3DGS);当FLAME mesh被驱动时,3DGS根据它的父亲三角面片,做平移、旋转和缩放变化;3DGS可以视作mesh上的辐射场࿱…...
进程地址空间(比特课总结)
一、进程地址空间 1. 环境变量 1 )⽤户级环境变量与系统级环境变量 全局属性:环境变量具有全局属性,会被⼦进程继承。例如当bash启动⼦进程时,环 境变量会⾃动传递给⼦进程。 本地变量限制:本地变量只在当前进程(ba…...
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以? 在 Golang 的面试中,map 类型的使用是一个常见的考点,其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...
DockerHub与私有镜像仓库在容器化中的应用与管理
哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...
练习(含atoi的模拟实现,自定义类型等练习)
一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...
8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂
蛋白质结合剂(如抗体、抑制肽)在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上,高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术,但这类方法普遍面临资源消耗巨大、研发周期冗长…...
STM32+rt-thread判断是否联网
一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...
蓝桥杯 2024 15届国赛 A组 儿童节快乐
P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡,轻快的音乐在耳边持续回荡,小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下,六一来了。 今天是六一儿童节,小蓝老师为了让大家在节…...
家政维修平台实战20:权限设计
目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系,主要是分成几个表,用户表我们是记录用户的基础信息,包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题,不同的角色…...
Nginx server_name 配置说明
Nginx 是一个高性能的反向代理和负载均衡服务器,其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机(Virtual Host)。 1. 简介 Nginx 使用 server_name 指令来确定…...
Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
