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

2024-03-10 22:04

本文主要是介绍突破编程_前端_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%;}table {  border-collapse: collapse;} 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; ,否则有可能设置列宽失败,表格宽度会超出父容器宽度。

这篇关于突破编程_前端_JS编程实例(自适应表格列宽)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/795666

相关文章

Oracle Expdp按条件导出指定表数据的方法实例

《OracleExpdp按条件导出指定表数据的方法实例》:本文主要介绍Oracle的expdp数据泵方式导出特定机构和时间范围的数据,并通过parfile文件进行条件限制和配置,文中通过代码介绍... 目录1.场景描述 2.方案分析3.实验验证 3.1 parfile文件3.2 expdp命令导出4.总结

Node.js 中 http 模块的深度剖析与实战应用小结

《Node.js中http模块的深度剖析与实战应用小结》本文详细介绍了Node.js中的http模块,从创建HTTP服务器、处理请求与响应,到获取请求参数,每个环节都通过代码示例进行解析,旨在帮... 目录Node.js 中 http 模块的深度剖析与实战应用一、引言二、创建 HTTP 服务器:基石搭建(一

React实现原生APP切换效果

《React实现原生APP切换效果》最近需要使用Hybrid的方式开发一个APP,交互和原生APP相似并且需要IM通信,本文给大家介绍了使用React实现原生APP切换效果,文中通过代码示例讲解的非常... 目录背景需求概览技术栈实现步骤根据 react-router-dom 文档配置好路由添加过渡动画使用

MySQL的索引失效的原因实例及解决方案

《MySQL的索引失效的原因实例及解决方案》这篇文章主要讨论了MySQL索引失效的常见原因及其解决方案,它涵盖了数据类型不匹配、隐式转换、函数或表达式、范围查询、LIKE查询、OR条件、全表扫描、索引... 目录1. 数据类型不匹配2. 隐式转换3. 函数或表达式4. 范围查询之后的列5. like 查询6

使用Vue.js报错:ReferenceError: “Vue is not defined“ 的原因与解决方案

《使用Vue.js报错:ReferenceError:“Vueisnotdefined“的原因与解决方案》在前端开发中,ReferenceError:Vueisnotdefined是一个常见... 目录一、错误描述二、错误成因分析三、解决方案1. 检查 vue.js 的引入方式2. 验证 npm 安装3.

vue如何监听对象或者数组某个属性的变化详解

《vue如何监听对象或者数组某个属性的变化详解》这篇文章主要给大家介绍了关于vue如何监听对象或者数组某个属性的变化,在Vue.js中可以通过watch监听属性变化并动态修改其他属性的值,watch通... 目录前言用watch监听深度监听使用计算属性watch和计算属性的区别在vue 3中使用watchE

C#反射编程之GetConstructor()方法解读

《C#反射编程之GetConstructor()方法解读》C#中Type类的GetConstructor()方法用于获取指定类型的构造函数,该方法有多个重载版本,可以根据不同的参数获取不同特性的构造函... 目录C# GetConstructor()方法有4个重载以GetConstructor(Type[]

python解析HTML并提取span标签中的文本

《python解析HTML并提取span标签中的文本》在网页开发和数据抓取过程中,我们经常需要从HTML页面中提取信息,尤其是span元素中的文本,span标签是一个行内元素,通常用于包装一小段文本或... 目录一、安装相关依赖二、html 页面结构三、使用 BeautifulSoup javascript

Python开发围棋游戏的实例代码(实现全部功能)

《Python开发围棋游戏的实例代码(实现全部功能)》围棋是一种古老而复杂的策略棋类游戏,起源于中国,已有超过2500年的历史,本文介绍了如何用Python开发一个简单的围棋游戏,实例代码涵盖了游戏的... 目录1. 围棋游戏概述1.1 游戏规则1.2 游戏设计思路2. 环境准备3. 创建棋盘3.1 棋盘类

Vue3 的 shallowRef 和 shallowReactive:优化性能

大家对 Vue3 的 ref 和 reactive 都很熟悉,那么对 shallowRef 和 shallowReactive 是否了解呢? 在编程和数据结构中,“shallow”(浅层)通常指对数据结构的最外层进行操作,而不递归地处理其内部或嵌套的数据。这种处理方式关注的是数据结构的第一层属性或元素,而忽略更深层次的嵌套内容。 1. 浅层与深层的对比 1.1 浅层(Shallow) 定义