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

news2025/6/15 17:12:34

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 中定义的 padding
                colMaxWidths[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; ,否则有可能设置列宽失败,表格宽度会超出父容器宽度。

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

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

相关文章

00X集——cad vba 中arc(弧)对象详解

弧是CAD中一个常见的图元&#xff0c;在vba中的类名为AcadArc,创建方法为set myarc thisdrawing.modelspace.addarc(Center, Radius, StartAngle, EndAngle) Center 圆心&#xff08;Variant[变体] (三元素双精度数组); 仅用于输入 指定圆弧圆心的三维WCS坐标。&#xff09; …

SpringBoot学习之自定义注解和AOP 切面统一保存操作日志(二十九)

一、定义一个注解 这个注解是用来控制是否需要保存操作日志的自定义注解(这个类似标记或者开关) package com.xu.demo.common.anotation;import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; i…

视频可回溯系统技术方案vue3+ts+tegg+mysql+redis+oss

一、 项目背景 保险、基金、银行等众多行业在做技术平台时都会需要一种能够准确了解用户操作行为的方式方法。诸如通过埋点、平台监控、视频可回溯等&#xff0c;通过技术手段&#xff0c;保存用户操作轨迹&#xff0c;以此规范安全销售、平台健康检查、出现纠纷时可追溯、问题…

round四舍五入在python2与python3版本间区别

round()方法返回数值的小数点四舍五入到n个数字。 语法 以下是round()方法的语法&#xff1a; round( x ,n) 参数 x --这是一个数值&#xff0c;表示需要格式化的数值 n --这也是一个数值,表示小数点后保留多少位 返回值 该方法返回 数值x 的小数点四舍五入到n个数字 …

现在海外问卷调查项目还能做么?

可以做。 目前比较好做的问卷渠道有ROM、YUNO等&#xff0c;都是非常优质的渠道&#xff0c;也是现在很多公司正在做的渠道。 这些渠道每天的题目数量是很多的&#xff0c;根本做不完。每天只要花时间做就能获得不错的收入。 我自己做这个项目很长时间了&#xff0c;这个项目…

Pytorch学习 day09(简单神经网络模型的搭建)

简单神经网络模型的搭建 针对CIFAR 10数据集的神经网络模型结构如下图&#xff1a; 由于上图的结构没有给出具体的padding、stride的值&#xff0c;所以我们需要根据以下公式&#xff0c;手动推算&#xff1a; 注意&#xff1a;当stride太大时&#xff0c;padding也会变得很大…

力扣日记3.6-【回溯算法篇】51. N 皇后

力扣日记&#xff1a;【回溯算法篇】51. N 皇后 日期&#xff1a;2023.3.6 参考&#xff1a;代码随想录、力扣 51. N 皇后 题目描述 难度&#xff1a;困难 按照国际象棋的规则&#xff0c;皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。 n 皇后问题 研究的是如何将…

008-slot插槽

slot插槽 1、插槽 slot 的简单使用2、插槽分类2.1 默认插槽2.2 具名插槽2.3 作用域插槽 插槽就是子组件中的提供给父组件使用的一个占位符&#xff0c;用<slot></slot> 表示&#xff0c;父组件可以在这个占位符中填充任何模板代码&#xff0c;如 HTML、组件等&…

【PHP+代码审计】PHP基础——数据类型

&#x1f36c; 博主介绍&#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 hacker-routing &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【应急响应】 【Java、PHP】 【VulnHub靶场复现】【面试分析】 &#x1f389;点赞➕评论➕收…

【滑动窗口】力扣239.滑动窗口最大值

前面的文章我们练习数十道 动态规划 的题目。相信小伙伴们对于动态规划的题目已经写的 得心应手 了。 还没看过的小伙伴赶快关注一下&#xff0c;学习如何 秒杀动态规划 吧&#xff01; 接下来我们开启一个新的篇章 —— 「滑动窗口」。 滑动窗口 滑动窗口 是一种基于 双指…

【大模型系列】根据文本检索目标(DINO/DINOv2/GroundingDINO)

文章目录 1 DINO(ICCV2021, Meta)1.1 数据增强1.2 损失函数 2 DINOv2(CVPR2023, Meta)2.1 数据采集方式2.2 训练方法 3 Grounding DINO3.1 Grounding DINO设计思路3.2 网络结构3.2.1 Feature Extraction and Enhancer3.2.2 Language-Guided Query Selection3.2.3 Cross-Modalit…

云原生构建 微服务、容器化与容器编排

第1章 何为云原生&#xff0c;云原生为何而生 SOA也就是面向服务的架构 软件架构的发展主要经历了集中式架构、分布式架构以及云原生架构这几代架构的发展。 微服务架构&#xff0c;其实是SOA的另外一种实现方式&#xff0c;属于SOA的子集。 在微服务架构下&#xff0c;系统…

sign加密方法生成

1. 引入包的问题 2. 原因 .pycrypto、pycrytodome和crypto是一个东西&#xff0c;crypto在python上面的名字是pycrypto&#xff0c;它是一个第三方库&#xff0c;但是已经停止更新 3. 解决方法 --直接安装&#xff1a;pip install pycryptodome 3.但是&#xff0c;在使用的时…

【C++进阶】哈希的应用 --- 布隆过滤器

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前学习C和算法 ✈️专栏&#xff1a;C航路 &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章对你有帮助的话 欢迎 评论&#x1f4ac; 点赞&#x1…

【leetcode】429. N 叉树的层序遍历

题目描述 给定一个 N 叉树&#xff0c;返回其节点值的_层序遍历_。&#xff08;即从左到右&#xff0c;逐层遍历&#xff09;。 树的序列化输入是用层序遍历&#xff0c;每组子节点都由 null 值分隔&#xff08;参见示例&#xff09;。 示例 1&#xff1a; 输入&#xff1a;…

BUUCTF-Misc6

数据包中的线索1 1.打开附件 发现是一个流量包 2.Wireshark 用Wireshark打开 右键属性&#xff0c;追踪tcp流&#xff0c;发现base64编码 3.base64转图片 将base64编码保存为文本文档 Python脚本 import os,base64 with open("/root/桌面/3/1.txt","r"…

基于SpringBoot+MYSQL的网上订餐系统

目录 1、 前言介绍 2、主要技术 3、系统功能分析 3.1、用户功能分析 3.2、管理员功能分析 4、系统结构分析 4.1、逻辑结构 4.2、物理结构 5、数据库设计 5.1、数据库E-R图设计 5.2、数据库表设计 6、运行截图(部分) 6.1、用户功能模块的实现 6.2、管理员功能模块的…

项目管理【引论一】项目管理的目标和高层次目标

系列文章目录 【引论一】项目管理的目标和高层次目标 一、项目管理的目标 项目管理的目标是在规定的时间内&#xff0c;在批准的预算内&#xff0c;完成事先确定的工作范围内的工作&#xff0c;并且达到预期的质量性能要求。 1.时间、成本和质量之间的关系 1.1时间、成本和…

YOLOv8.1.0安装

【YOLO】YOLOv8训练环境配置 python 3.8.18 cuda 11.3.1 cudnn 8.2.1 pytorch 1.12.1-gpu版 - 知乎 (zhihu.com) 一、Anaconda 默认装好了可用的Anaconda&#xff0c;安装教程见Win10系统anaconda安装 - 知乎 (zhihu.com) 二、在虚拟环境下用conda安装 1.创建虚拟环境 …

transformer--使用transformer构建语言模型

什么是语言模型? 以一个符合语言规律的序列为输入&#xff0c;模型将利用序列间关系等特征&#xff0c;输出一个在所有词汇上的概率分布.这样的模型称为语言模型. # 语言模型的训练语料一般来自于文章&#xff0c;对应的源文本和目标文本形如: src1"Ican do",tgt1…