突破编程_前端_JS编程实例(自适应表格列宽)

1 开发目标

针对如下的表格组件:

在这里插入图片描述

根据表格的各个列字符串宽度动态调整表格列宽:

在这里插入图片描述

2 详细需求

本组件目标是提供一个自动调整 HTML 表格列宽的解决方案,通过 JS 实现动态计算并调整表格每列的宽度,以使得表格能够自适应容器宽度,同时保持列宽的合理性。

2.1 容器与表格元素获取

  • 组件需根据传入的容器获取其子元素集合中的表格元素。
  • 计算每列中最长字符串所占的宽度:最长字符串宽度的计算应基于字符串的渲染宽度,而非简单的字符数,以考虑不同字符宽度的差异。

2.2 列宽调整规则

  • 组件需根据计算出的每列最长宽度,调整每一列的列宽。
  • 调整后的表格宽度需占满其父容器的宽度。
  • 若所有列的最长宽度之和不大于传入容器的宽度,则按照各自最长宽度所占的比例调整每一列的列宽,以确保表格充分利用可用空间。
  • 若所有列的最长宽度之和大于传入容器的宽度,则按照以下优先级进行调整:
    • 最长宽度不大于 100px 的列,直接按其最长宽度设置列宽。
    • 对于其他列,按照各自最长宽度所占的比例调整列宽,以在有限的空间内尽可能保持列宽的合理性。
    • 若全部最长宽度不大于 100px 的列的列宽之和已经大于传入容器的宽度,则所有列均按照各自最长宽度所占的比例调整列宽,以确保表格不会超出容器宽度。

3 代码实现

首先创建一个 neat_tableparse.js 文件,该文件用于本组件的工具类、表格自适应处理函数的代码构建。

(1)在具体的业务代码编写之前,先实现一个工具类以及一些工具方法,方便后面调用:

class CommonUtil {// 计算文本在页面所占 px 宽度static calcTextWidth(str, fontSize) {let span = document.createElement('span');document.body.appendChild(span);span.innerHTML = str;span.style.visibility = 'hidden';if(fontSize){span.style.fontSize = fontSize;}let width = span.offsetWidth;document.body.removeChild(span);return width;}
}

(2)接下来,定义一个处理表格自适应列宽的函数:

function parseTable(table) {// 最长宽度不大于该变量的列,直接按其最长宽度设置列宽// 若全部最长宽度不大于该变量的列的列宽之和已经大于传入容器的宽度,则所有列均按照各自最长宽度所占的比例调整列宽,以确保表格不会超出容器宽度const miniShowWidth = 100;

其中,定义了一个变量 miniShowWidth,该变量是指:最长宽度不大于该变量的列,直接按其最长宽度设置列宽。

(3)然后,获取每列最长宽度,将其存入 colMaxWidths 数组中:

	// 获取每列最长宽度,将其存入 colMaxWidths 数组中let colMaxWidths = [];let trs = table.getElementsByTagName('tr');if (!trs) {return;}for (let i = 0; i < trs.length; i++) {const tr = trs[i];let objs = null;objs = tr.getElementsByTagName('th');if (!objs || objs.length == 0) {objs = tr.getElementsByTagName('td');}if (!objs || objs.length == 0) {return;}if (objs.length > 0) {for (let index = 0; index < objs.length; index++) {const obj = objs[index];if (colMaxWidths.length <= index) {colMaxWidths.push(0);}let width = CommonUtil.calcTextWidth(obj.innerText) + 16 ;   //这里的 16 是在 css 中定义的 paddingcolMaxWidths[index] = (colMaxWidths[index] > width) ? colMaxWidths[index] : width;}}}

(4)本函数是通过对 colgroups 的子元素 col 的宽度设置来控制表格列宽的自适应,所以接下来需要获取或创建 colgroup 元素,以及创建或补齐 col 元素:

	// 获取或创建 colgroup 元素let colgroups = table.getElementsByTagName('colgroup');if (!colgroups || 0 == colgroups.length) {let colgroup = document.createElement('colgroup');table.appendChild(colgroup);colgroups = table.getElementsByTagName('colgroup');}// 创建或补齐 col 元素let cols = colgroups[0].getElementsByTagName('col');let colNum = cols ? cols.length : 0;for (let index = colNum; index < colMaxWidths.length; index++) {let col = document.createElement('col');colgroups[0].appendChild(col);}cols = colgroups[0].getElementsByTagName('col');

(5)根据需求中对不同宽度的列处理,首先需要获取父容器宽度以及获取所有列的最长宽度之和:

	// 获取父容器宽度let parentWidth = table.parentElement.offsetWidth;// 获取所有列的最长宽度之和let sumColMaxWidth = 0;colMaxWidths.forEach(element => {sumColMaxWidth += element;});

(6)若所有列的最长宽度之和不大于传入容器的宽度,则按照各自最长宽度所占的比例调整每一列的列宽:

	if (sumColMaxWidth <= parentWidth) {    // 若所有列的最长宽度之和不大于传入容器的宽度,则按照各自最长宽度所占的比例调整每一列的列宽for (let index = 0; index < colMaxWidths.length; index++) {cols[index].width = (colMaxWidths[index] / sumColMaxWidth) * parentWidth + 'px';}} 

(7)否则则处理全部最长宽度不大于 miniShowWidth 的列的列宽之和小于传入容器的宽度:

	else {// 获取所有列的最长宽度不大于 miniShowWidth 的列的列宽之和let sumColMiniShowWidth = 0;let sumOtherColsMaxWidth = 0;colMaxWidths.forEach(element => {if(element <= miniShowWidth){sumColMiniShowWidth += element;}else{sumOtherColsMaxWidth += element;}});if(sumColMiniShowWidth < parentWidth){ //若全部最长宽度不大于 miniShowWidth 的列的列宽之和小于传入容器的宽度let parentWidthOffset = parentWidth-sumColMiniShowWidth;for (let index = 0; index < colMaxWidths.length; index++) {if(colMaxWidths[index] > miniShowWidth && sumOtherColsMaxWidth>0){cols[index].width = (colMaxWidths[index] / sumOtherColsMaxWidth) * parentWidthOffset + 'px';}else{cols[index].width = miniShowWidth + 'px';}}}

(8)最后处理若全部最长宽度不大于 sumColMaxWidth 的列的列宽之和已经大于传入容器的宽度,则所有列均按照各自最长宽度所占的比例调整列宽,以确保表格不会超出容器宽度:

		else{  // 若全部最长宽度不大于 sumColMaxWidth 的列的列宽之和已经大于传入容器的宽度,则所有列均按照各自最长宽度所占的比例调整列宽,以确保表格不会超出容器宽度。for (let index = 0; index < colMaxWidths.length; index++) {cols[index].width = (colMaxWidths[index] / sumColMaxWidth) * parentWidth + 'px';}}}
}

至此,整个处理表格自适应列宽的函数构建结束。

(9)完成自适应表格列宽函数的代码编写后,可以创建 neat_tableparse.html 文件,调用该函数:

<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta http-equiv="X-UA-Compatible" content="ie=edge" /><title>header tab</title><style>html {height: 100%;}body {margin: 0;height: 100%;}th,td {border: 1px solid #ddd;padding: 8px;text-align: left;word-break: break-all;}th {background-color: #f2f2f2;}</style>
</head><body><div id="divMain" style="margin-top: 100px;margin-left: 100px;height: 400px;width: 600px;border: 1px solid #aaa;overflow: hidden;"><table cellspacing="0" ><thead><tr><th>col1</th><th>col2列2</th><th>col3</th></tr></thead><tbody><tr><td>val_1_1</td><td>val_1_2</td><td>val_1_3</td></tr><tr><td>val_2_1</td><td>val_2_2</td><td>val_2_322222222222222</td></tr><tr><td>val_3_1</td><td>val_3_2</td><td>val_3_3</td></tr></tbody></table></div>
</body>
<script src="./test.js"></script>
<script>let container = document.getElementById('divMain');let tables = container.querySelectorAll("table");tables.forEach(element => {parseTable(element);});
</script></html>

重点注意:样式表中,要将 td 的单词中断设置为: break-all; ,否则有可能设置列宽失败,表格宽度会超出父容器宽度。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/729985.shtml

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

相关文章

微信作为私域营销的载体有哪些优势?

私域流量的本质就是&#xff1a; 降低我的获客成本&#xff0c;提高我产品服务的复购率&#xff0c;增加我和用户之间的粘性&#xff0c;挖掘用户的终身价值。 私域流量的优势&#xff1a; 1、更精准&#xff1b; 2、节约成本&#xff0c;减少广告成本&#xff1b; 3、有利于品…

LCR 179. 查找总价格为目标值的两个商品 - 力扣

1. 题目 购物车内的商品价格按照升序记录于数组 price。请在购物车中找到两个商品的价格总和刚好是 target。若存在多种情况&#xff0c;返回任一结果即可。 2. 示例 3. 分析 我们首先想到暴力解法&#xff0c;这道题目的暴力还是比较简单的&#xff0c;列举每个数的情况即可…

C/C++的内存管理与初阶模板

引言 我们在学习C的时候&#xff0c;会经常在堆上申请空间&#xff0c;所以这个时候就体现了内存管理遍历。 图下是我们常见的计算机的内存划分&#xff1a; 我也在图下对部分变量存在的位置&#xff0c;及时标注。(如果有任何问题可以联系博主修改&#xff0c;感谢大家。) 那…

智慧油气场站:油气行业实现数字化转型的关键一步

智慧油气场站&#xff1a;油气行业实现数字化转型的关键一步 在现代社会&#xff0c;能源供应是国家经济发展和人民生活的重要保障。而油气场站作为能源的重要供应和储存基地&#xff0c;扮演着至关重要的角色。此外&#xff0c;油气场站还可以为石油和天然气的生产提供支持。…

Docker安装主从数据库

我自己的主数据库名字 user_muster 密码是123456 从数据库 就是slave2 名字是root 密码是123456 首先开启docker后直接执行命令 docker run -d \ -p 3307:3306 \ -v /xk857/mysql/master/conf:/etc/mysql/conf.d \ -v /xk857/mysql/master/data:/var/lib/mysql \ -e MYSQL_…

【随笔】程序员的金三银四求职宝典,每个人都有最合适自己的求职宝典

大家好&#xff0c;我是全栈小5&#xff0c;欢迎阅读文章&#xff01; 此篇是【话题达人】系列文章&#xff0c;这一次的话题是《程序员的金三银四求职宝典》 目录 背景能力流程图求职宝典就业数据人数曲线图增长率柱状图 其他建议文章推荐 背景 随着春天的脚步渐近&#xff0…

【JavaEE初阶】 关于JVM垃圾回收

文章目录 &#x1f343;前言&#x1f38b;死亡对象的判断算法&#x1f6a9;引用计数算法&#x1f6a9;可达性分析算法 &#x1f333;垃圾回收算法&#x1f6a9;标记-清除算法&#x1f6a9;复制算法&#x1f6a9;标记-整理算法&#x1f6a9;分代算法&#x1f388;哪些对象会进入…

Redis与 Memcache区别

Redis与 Memcache区别 1 , Redis 和 Memcache 都是将数据存放在内存中&#xff0c;都是内存数据库。不过 Memcache 还可用于缓存 其他东西&#xff0c;例如图片、视频等等。 2 , Memcache 仅支持key-value结构的数据类型&#xff0c;Redis不仅仅支持简单的key-value类型的数据&…

STM32 | Proteus 8.6安装步骤(图文并茂)

01 Proteus 8.6 简介 Proteus 8.6 是一款功能强大的电子设计自动化软件&#xff0c;广泛用于电路设计、仿真和PCB布局。它为电子工程师和学生提供了一个全面的工具集&#xff0c;用于设计和验证各种电路和电子设备。Proteus 8.6 包括了以下几个主要特性&#xff1a; 1. 电路设…

力扣404. 左叶子之和(java)

//当前节点的左子树不为空 且是叶子节点 root.left ! null &&root.left.leftnull && root.left.rightnull/*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* …

git分布式管理-头歌实验搭建Git服务器

一、Git服务器搭建 任务描述 虽然有提供托管代码服务的公共平台&#xff0c;但是对一部分开发团队来说&#xff0c;为了不泄露项目源代码、节省费用及为项目提供更好的安全保护&#xff0c;往往需要搭建私有Git服务器用做远程仓库。Git服务器为团队的开发者们&#xff0c;提供了…

洛谷 P8816 [CSP-J 2022] 上升点列(T4)

目录 题目传送门 算法解析 最终代码 提交结果 尾声 题目传送门 [CSP-J 2022] 上升点列 - 洛谷https://www.luogu.com.cn/problem/P8816 算法解析 k 0 且 xi, yi 值域不大时&#xff0c;这题是非常简单的 DP&#xff0c;类似「数字三角形」。 记 dp(x,y) 为「以 (x,y) …

tomcat基础介绍

目录 一、Tomcat的基本介绍 1、Tomcat是什么&#xff1f; 2、Tomcat的配置文件详解 3、Tomcat的构成组件 6、Tomcat的请求过程 一、Tomcat的基本介绍 1、Tomcat是什么&#xff1f; Tomcat 服务器是一个免费的开放源代码的Web 应用服务器&#xff0c;属于轻量级应用服务器…

植物病虫害:YOLO玉米病虫害识别数据集

玉米病虫害识别数据集&#xff1a;玉米枯萎病&#xff0c;玉米灰斑病&#xff0c;玉米锈病叶&#xff0c;粘虫幼虫&#xff0c;玉米条斑病&#xff0c;黄二化螟&#xff0c;黄二化螟幼虫7类&#xff0c;yolo标注完整&#xff0c;3900多张图像&#xff0c;全部原始数据&#xff…

二、TensorFlow结构分析(4)

TF数据流图图与TensorBoard会话张量Tensor变量OP高级API 目录 1、变量 2、高级API 1、变量 2、高级API

RFID技术进阶:频段选择的艺术与科学

RFID技术进阶&#xff1a;频段选择的艺术与科学 在数字化、自动化的浪潮中&#xff0c;RFID&#xff08;无线射频识别&#xff09;技术以其独特的优势&#xff0c;逐渐在多个领域占据了一席之地。RFID&#xff08;Radio Frequency Identification&#xff09;&#xff0c;即无…

24/03/07总结

esayx: 贪吃蛇: #include "iostream" #include "cmath" #include "conio.h" #include "easyx.h" #include "time.h" #define NODE_WIDTH 40 using namespace std; typedef struct {int x;int y; }node; enum direction /…

C++ Lambda函数

lambda语法 [capture list] (parameter list) specifiers exception -> type { function body }[capture list]是捕获列表&#xff0c;在应用中必填。 (parameter list)是参数列表&#xff0c;在应用中选填。 specifiers是限定符&#xff0c;在应用中选填。 exception是…

Java对接腾讯云直播示例

首先是官网的文档地址 云直播 新手指南 可以发现它这个主要是按流量和功能收费的 价格总览 流量这里还只收下行的费用&#xff0c;就是只收观看消耗的流量费 其它的收费就是一些增值业务费 &#xff08;包括直播转码、直播录制、直播截图、直播审核、智能鉴黄、实时监播、移动直…

【性能测试】Jmeter性能压测-阶梯式/波浪式场景总结(详细)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、阶梯式场景&am…