ElementUI中的el-table解决宽度问题 - 根据内容自动撑开

        在使用element-ui中,会发现表格组件el-table在未指定宽度情况下,会自动计算并给表格宽度赋值。但实际开发中,有时需要根据内容实际长度自动撑开显示,由内容的多少而决定表格的宽度,而不是默认宽度为100%。在默认情况下表格宽度为100%显示,并且列项未指定宽度情况下,剩余部分会平均分配宽度,如下图:

图1-默认情况宽度为100%

        本案例实际需求如下图所示,由内容自动撑开显示。

图2-根据内容自动撑开

一、演示页面

        首先创建Vue2项目,并新建演示页面,页面代码如下:

<template>
  <div>
    <el-table size="mini" border :data="tableData">
      <el-table-column type="index" label="序号" width="50px"></el-table-column>
      <el-table-column label="名称" prop="name"></el-table-column>
      <el-table-column label="内容" prop="content"></el-table-column>
      <el-table-column label="图片" prop="thumb">
        <template slot-scope="scope">
          <div class="thumb">
            <img v-if="scope.row.thumb" :src="scope.row.thumb" class="img" />
          </div>
        </template>
      </el-table-column>
      <el-table-column label="创建时间" prop="createtime"></el-table-column>
      <el-table-column label="更新时间" prop="updatetime"></el-table-column>
    </el-table>
  </div>
</template>

<script>
import AutoTable from './autoTable'
export default {
  data(){
    return {
      tableData: [
        {name: "Angular", content: "This is Angular Javascript", thumb: require("@/assets/angular.jpg"), createtime: "2024/6/15", updatetime: "2024/6/15"},
        {name: "VueJs", content: "This is Vue Javascript", thumb: require("@/assets/logo.png"), createtime: "2024/6/15", updatetime: "2024/6/15"},
        {name: "NuxtJs", content: "This is Nuxt Javascript", thumb: require("@/assets/nuxtjs.jpg"), createtime: "2024/6/15", updatetime: "2024/6/15"},
        {name: "React", content: "This is React Javascript", thumb: require("@/assets/react.jpg"), createtime: "2024/6/15", updatetime: "2024/6/15"},
        {name: "Dog", content: "This is Dog Javascript", thumb: require("@/assets/dog.jpg"), createtime: "2024/6/15", updatetime: "2024/6/15"}
      ]
    }
  }
}
</script>

<style lang="less" scoped>
.thumb{
  position: relative;
  img{ display: block; }

  .img{
    width: 30px;
  }
  .hover{
    display: none;
    width: 200px;
    position: absolute;
    left: 35px;
    top: 0;
    z-index: 1000;
  }

  &:hover{
    .hover{ display: block; }
  }
}
</style>

        以上代码创建好后,显示为“图1”中的效果。

二、样式调整

        如下图所示,element-ui中默认表格样式.cell为块级元素,为了能获取到内容真实的宽度,这里需要将其修改为行内块,这样就能获取到内容的宽度了。

        这里使用的是less预编译器,样式代码如下:

<style lang="less" scoped>
// 略...

/deep/ .el-table .cell{ display: inline-block; }
/deep/ .el-table th.el-table__cell>.cell{ display: inline-block; width: auto; }
</style>

        如上图,样式内容添加后,选择元素则是按内容实际宽度区域进行显示。

三、directives中定义钩子函数

        Vue.directive构子函数对于组件中元素的改造是非常方便的,此时需要添加一个可以自动处理表格宽度的自定义指令,用于统一处理项目中需要根据内容自动撑开的表格。

        对于Vue.directive介绍之前一篇已介绍过,不清楚朋友可以前去了解一下,地址:Element-UI - 解决el-table中图片悬浮被遮挡问题_vuetable的图片放大后总是浮于文字下方-CSDN博客

        由于本人项目将表格组件进行了封装,所以这里使用局部自定义指令方法,如需全局处理可以将其功能移至全局文件中定义。

        代码如下:

export default {
  data(){
    return {
      tableData: [
        {name: "Angular", content: "This is Angular Javascript", thumb: require("@/assets/angular.jpg"), createtime: "2024/6/15", updatetime: "2024/6/15"},
        {name: "VueJs", content: "This is Vue Javascript", thumb: require("@/assets/logo.png"), createtime: "2024/6/15", updatetime: "2024/6/15"},
        {name: "NuxtJs", content: "This is Nuxt Javascript", thumb: require("@/assets/nuxtjs.jpg"), createtime: "2024/6/15", updatetime: "2024/6/15"},
        {name: "React", content: "This is React Javascript", thumb: require("@/assets/react.jpg"), createtime: "2024/6/15", updatetime: "2024/6/15"},
        {name: "Dog", content: "This is Dog Javascript", thumb: require("@/assets/dog.jpg"), createtime: "2024/6/15", updatetime: "2024/6/15"}
      ]
    }
  },
  directives: {
    // 自定义v-autotable
    autotable: {
      inserted: (el, binding) =>  {}
    }
  },
}

        注意:自定义指令中inserted钩子函数是在被绑定元素插入父节点时调用,只执行一次。

四、定义AutoTable类

        定义AutoTable类,用于获取每列内容的实际宽度,并通过获取每列中最大的内容宽度计算出表格的宽。
       代码如下:

/**
 * 定义类 - 自定义表格宽度
 */
class AutoTable{
  constructor(){
    this.timerHandle = null;        //计时器手柄
  }
  // 开始重新计算表格宽度
  start(el, binding){
    
  }
}
export default AutoTable;

        本类计时器是用于延迟获取内容部分DOM,当内容读取到后通过或满足某些条件后,通过this.timerHandle进行清除计时器。

五、修改表格宽度

        如下图可见,element-ui中的表格组件,是分头部标题部分和内容部分。所以要分两部分获取,先获取头部对应列内容的宽度,再获取内容部分的列中所有内容的宽度,合并到一个数组中,筛选出每列中的最大宽度作为列宽。

        下面实现原理和逻辑就不作细说了,每行代码都已添加备注并说明作用,大家可以慢慢细品。代码如下:

/**
 * 定义类 - 修正表格宽度
 */
class AutoTable{
  constructor(){
    this.timerHandle = null;        //计时器手柄
  }
  // 开始重新计算表格宽度
  start(el, binding){
    // 如果值为false, 则不进行计算处理
    if(!binding.value) return;
    const headerDOM = el.querySelector('.el-table__header-wrapper'),      // 头部DOM
          bodyDOM = el.querySelector('.el-table__body-wrapper');          // 内容DOM
    // 先清除旧计时器
    clearInterval(this.timerHandle);
    // 开始计时
    this.timerHandle = setInterval(() => {
      const tds = bodyDOM.querySelectorAll('table tbody tr'),             // 获取内容行数
            ths = headerDOM.querySelectorAll('table thead th .cell'),       // 获取头部列元素
            emptyDOM = el.querySelector('.el-table__empty-text');         // 获取空DOM节点
     
      // 如果满足条件,结束计时器
      if(null != emptyDOM || tds.length>0) {
        clearInterval(this.timerHandle);
      }
      if(tds.length == 0 && ths.length == 0)  return;

      // 定义变量 存储每列的宽度数据
      const widths = [];            // 二维数组,存储行和列数据
      // 获取标题中的单元格宽度
      ths.forEach((item, i) => widths[i] = [item.offsetWidth]);
      // 获取内容部分列的单元格宽度
      tds.forEach(trEle => {
        const cells = trEle.querySelectorAll('td .cell');
        cells.forEach((item, i) => widths[i].push(item.offsetWidth))
      });
      // 定义存储每列中最大值宽度数组
      const maxWidth = [];
      // 获取每列中宽度最大值内容
      widths.forEach((arr, i) => maxWidth[i] = arr.reduce((maxValue, item) => Math.max(maxValue, item), arr[0]));
      // 定义变量存储表格宽度(追加内填充10)
      const realWidth = maxWidth.reduce((total, value) => total + value, 0) + (maxWidth.length * 10);
      // 修改表格宽度
      if(realWidth>0) el.style.width = realWidth + 'px';
    }, 50);
  }
}

export default AutoTable;

        页面中在el-table标签上添加v-autotable,并且引入autotable.js文件,在组件注册插入时,实例类对象并执行start()函数,代码如下:

<template>
  <div>
    <el-table size="mini" border :data="tableData"  v-autotable="true">
      <el-table-column type="index" label="序号" width="50px"></el-table-column>
      <el-table-column label="名称" prop="name"></el-table-column>
      <el-table-column label="内容" prop="content"></el-table-column>
      <el-table-column label="图片" prop="thumb">
        <template slot-scope="scope">
          <div class="thumb">
            <img v-if="scope.row.thumb" :src="scope.row.thumb" class="img" />
          </div>
        </template>
      </el-table-column>
      <el-table-column label="创建时间" prop="createtime"></el-table-column>
      <el-table-column label="更新时间" prop="updatetime"></el-table-column>
    </el-table>
  </div>
</template>

<script>
import AutoTable from './autoTable'
export default {
  data(){
    return {
      tableData: [
        {name: "Angular", content: "This is Angular Javascript", thumb: require("@/assets/angular.jpg"), createtime: "2024/6/15", updatetime: "2024/6/15"},
        {name: "VueJs", content: "This is Vue Javascript", thumb: require("@/assets/logo.png"), createtime: "2024/6/15", updatetime: "2024/6/15"},
        {name: "NuxtJs", content: "This is Nuxt Javascript", thumb: require("@/assets/nuxtjs.jpg"), createtime: "2024/6/15", updatetime: "2024/6/15"},
        {name: "React", content: "This is React Javascript", thumb: require("@/assets/react.jpg"), createtime: "2024/6/15", updatetime: "2024/6/15"},
        {name: "Dog", content: "This is Dog Javascript", thumb: require("@/assets/dog.jpg"), createtime: "2024/6/15", updatetime: "2024/6/15"}
      ]
    }
  },
  directives: {
    // 自定义悬浮v-autotable
    autotable: {
      inserted: (el, binding) =>  new AutoTable().start(el, binding),
    }
  },
}
</script>

        此时页面效果如下图,细心朋友会发现此时未指定列宽部分的列,是等宽显示并出现换行的情况,并未按每列最大实际宽度显示,这个问题下面再细讲。

六、colgroup

        在解决列宽问题前,先来了解下colgroup。< colgroup > 元素用于设置表的特定列的样式,< colgroup > 元素应该用作列规范的容器,每个组都使用 < col> 元素指定,span 属性指定获取样式的列数,style 属性指定列的样式。

注意: < colgroup > 标记必须是一个 < table > 元素的子元素,并且应该放在任何其他表元素之前,如 < head > 、 < tr > 、 < td > 等,但是如果存在的话,应该放在 < caption > 元素之后。

        在 colgroup 中允许使用的 CSS 属性的选择非常有限,合法 CSS 属性如下:

名称描述
width设置宽度
visibility是否可见
background背景样式
border边界线

        所有其他 CSS 属性对表没有影响。

七、修整每列的宽度

        如下图可见,Element-ui组件中表格的列宽,是通过colgroup > col对每列宽进行控制的;所以要控制每列的宽度,则需要将其修正为之前获取第列内容宽最大值即可。

        代码如下:

class AutoTable{
  // 略...
  
  // 开始重新计算表格宽度
  start(el, binding){
    // 如果值为false, 则不进行计算处理
    if(!binding.value) return;

    const headerDOM = el.querySelector('.el-table__header-wrapper'),      // 头部DOM
          bodyDOM = el.querySelector('.el-table__body-wrapper');          // 内容DOM
    // 先清除旧计时器
    clearInterval(this.timerHandle);
    // 开始计时
    this.timerHandle = setInterval(() => {
      const tds = bodyDOM.querySelectorAll('table tbody tr'),             // 获取内容行数
            ths = headerDOM.querySelectorAll('table thead th .cell'),       // 获取头部列元素
            emptyDOM = el.querySelector('.el-table__empty-text');         // 获取空DOM节点

      // 略...
	  
      // 修改表格宽度
      if(realWidth>0) el.style.width = realWidth + 'px';

      // 获取colgroup
      const headerColGroup = headerDOM.querySelectorAll('colgroup col'),
            bodyColGroup = bodyDOM.querySelectorAll('colgroup col');
      // 修改每列宽度
      maxWidth.forEach((val, i) => {
        headerColGroup[i].style.width = val + 'px';
        bodyColGroup[i].style.width = val + 'px';
      });
    }, 50);
  }
}

        通过获取表格header中的colgroup > col 和body中的colgroup > col元素,再通过将第列中最大内容宽度赋值到对应列的col上即可。当上述代码执行后,再查看col属性则发现列的值已发生改变,如下图:

        页面效果如下图,此时第列中都以最大内容宽度显示,表格宽度根据内容长度变化而改变。

八、更新宽度

        由于inserted是在元素第一次插入时执行,只调用一次,所以当表格中数据变化,就需要使用到update和componentUpdated了。这里使用componentUpdated,它是在指令所在组件的 VNode 及其子 VNode 全部更新后调用。

        代码如下:

import AutoTable from './autoTable'
export default {
  data(){
    return {
      tableData: [
        {name: "Angular", content: "This is Angular Javascript", thumb: require("@/assets/angular.jpg"), createtime: "2024/6/15", updatetime: "2024/6/15"},
        {name: "VueJs", content: "This is Vue Javascript", thumb: require("@/assets/logo.png"), createtime: "2024/6/15", updatetime: "2024/6/15"},
        {name: "NuxtJs", content: "This is Nuxt Javascript", thumb: require("@/assets/nuxtjs.jpg"), createtime: "2024/6/15", updatetime: "2024/6/15"},
        {name: "React", content: "This is React Javascript", thumb: require("@/assets/react.jpg"), createtime: "2024/6/15", updatetime: "2024/6/15"},
        {name: "Dog", content: "This is Dog Javascript", thumb: require("@/assets/dog.jpg"), createtime: "2024/6/15", updatetime: "2024/6/15"}
      ]
    }
  },
  directives: {
    // 自定义悬浮v-autotable
    autotable: {
      inserted: (el, binding) =>  new AutoTable().start(el, binding),
	  componentUpdated: (el, binding) =>  new AutoTable().start(el, binding)
    }
  },
}

        虽然此方法不是真正意义上根据内容宽度自动撑开的,但也达到了预期中的效果,希望对大家有所帮助。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

韩语日常口语留学韩语旅游韩语口语柯桥语言培训

韩语每日一词打卡&#xff1a;행정적[행정적]【名词】行政 原文:나라는 항상 행정적 명령을 통해 경제운행을 조절합니다. 意思&#xff1a;国家经常通过行政命令去调节经济的运行。 【原文分解】 1、항상[항상]总是 &#xff0c;经常 2、나라[나라]国家 3、명령[명:녕]命令 …

计算机网络——数据链路层(点对点协议PPP)

点对点协议PPP的概述 对于点对点的链路&#xff0c;目前使用得最广泛的数据链路层协议是点对点协议 PPP (Point-to-Point Protocol)。 它主要应用于两个场景&#xff1a; 用户计算机与ISP之间的链路层协议就是点对点协议 PPP&#xff0c;1999年公布了回以在以太网上运行的PPP协…

JAVA每日作业day7.1-7.3小总结

ok了家人们前几天学了一些知识&#xff0c;接下来一起看看吧 一.API Java 的 API &#xff08; API: Application( 应用 ) Programming( 程序 ) Interface(接口 ) &#xff09; Java API 就是 JDK 中提供给我们使用的类&#xff0c;这些类将底层 的代码实现封装了起来&#x…

10 docker 安装 mysql详解

目录 一、安装mysql 1. 镜像获取 2. 简单版 2.1. 使用mysql镜像 2.2. 建库建表插入数据 2.3. 外部win 连接并插入中文数据测试 2.4. 简单版本问题 3. 创建容器-实战版 3.1. 新建容器实列并挂载卷 3.2. 新建my.cnf , 解决中文乱码 3.3. 重启容器验证 3.4. 总结 一、…

2024年精选推荐的16个向量数据库:提升你的AI应用性能

在人工智能时代&#xff0c;向量数据库已成为数据管理和AI模型不可或缺的一部分。向量数据库是一种专门设计用来存储和查询向量嵌入数据的数据库。这些向量嵌入是AI模型用于识别模式、关联和潜在结构的关键数据表示。随着AI和机器学习应用的普及&#xff0c;这些模型生成的嵌入…

聊一聊领域驱动和贫血

写在前面 前段时间跟领导讨论技术债概念时不可避免地提到了代码的质量&#xff0c;而影响代码质量的因素向来都不是单一的&#xff0c;诸如项目因素、管理因素、技术选型、人员素质等等&#xff0c;因为是技术债务&#xff0c;自然就从技术角度来分析&#xff0c;单纯从技术角…

UOS系统中JavaFx笔锋功能

关于笔锋功能&#xff0c;网上找了很久&#xff0c;包括Java平台客户端&#xff0c;Android端&#xff0c;相关代码资料比较少&#xff0c;找了很多经过测试效果都差强人意&#xff0c;自己也搓不出来&#xff0c;在UOS平台上JavaFX也获取不到压力值&#xff0c;只能用速度的变…

c++习题07-求小数的某一位

目录 一&#xff0c;问题 二&#xff0c;思路 三&#xff0c;代码 一&#xff0c;问题 二&#xff0c;思路 被除数a的类型设置为long long类型&#xff0c;a变量需要变大&#xff0c;需要更大的数据类型来存储除数b和指定的小数位置n为int类型&#xff0c;这两个变量的的…

计算机图形学入门23:蒙特卡洛路径追踪

1.前言 前面几篇文章介绍了Whitted-style光线追踪&#xff0c;还介绍了基于物理渲染的基础知识&#xff0c;包括辐射度量学、BRDF以及渲染方程&#xff0c;但并没有给出解渲染方程的方法&#xff0c;或者说如何通过该渲染方程计算出屏幕上每一个坐标的像素值。 Whitted-style光…

未来的钥匙在于过去:学历史的真正意义,震惊!历史竟然是偶然的?从历史中寻找未来的方向!

我们自幼接受的教育是&#xff0c;学历史是为了相信历史是必然的。中国人民必然战胜日寇的侵略&#xff0c;解放思想和改革开放必定会发生&#xff0c;和平和发展必定是世界的主题&#xff0c;中国经济必定是高速增长…… 然而&#xff0c;在真正的历史学家眼中&#xff0c;历史…

1分钟了解,预写日志WAL的核心思路...

上一篇《刷盘&#xff0c;还是不刷盘&#xff0c;是一个问题》中我们遇到了哪些问题&#xff1f; 1. 已提交事务未提交事务的ACID特性怎么保证&#xff1f; 画外音&#xff1a;上一篇中遇到的问题&#xff0c;主要是原子性与持久性。 2. 数据库崩溃&#xff0c;怎么实施故障恢复…

新声创新20年:无线技术给助听器插上“娱乐”的翅膀

听力损失并非现代人的专利&#xff0c;古代人也会有听力损失。助听器距今发展已经有二百多年了&#xff0c;从当初单纯的声音放大器到如今的全数字时代助听器&#xff0c;助听器发生了翻天覆地的变化&#xff0c;现代助听器除了助听功能&#xff0c;还具有看电视&#xff0c;听…

AD导入.step 3D封装

在网站查找想要的3D封装 https://www.3dcontentcentral.cn/ 下载 AD导入 在封装库下导入

融云上线 HarmonyOS NEXT 版 SDK,全面适配「纯血鸿蒙」生态

6 月 21 日&#xff0c;“2024 华为开发者大会”正式发布使用自研内核的原生鸿蒙系统 HarmonyOS NEXT&#xff0c;即 “纯血鸿蒙”。 同时&#xff0c;华为宣布开放“鸿蒙生态伙伴 SDK 市场”&#xff0c;甄选各类优质、安全的 SDK 加入聚合平台&#xff0c;助力各行业开发者轻…

数据结构初阶 堆的问题详解(三)

题目一 4.一棵完全二叉树的节点数位为531个&#xff0c;那么这棵树的高度为&#xff08; &#xff09; A 11 B 10 C 8 D 12 我们有最大的节点如下 假设最大高度为10 那么它的最多节点应该是有1023 假设最大高度为9 那么它的最多节点应该是 511 所以说这一题选B 题目二 …

08 docker Registry搭建docker私仓

目录 本地镜像发布流程 1. docker pull registry 下载镜像 2. docker run 运行私有库registry 3. docker commit 构建镜像 4. docker tag 修改新镜像&#xff0c;使之符合私服规范tag 5. 修改配置文件使之支持http 6. curl验证私服库上有什么镜像 7. push推送 pull拉取 …

Jenkins教程-13-参数化任务构建

上一小节我们学习了发送html邮件测试报告的方法&#xff0c;本小节我们讲解一下Jenkins参数化任务构建的方法。 很多时候我们需要根据不同的条件去执行构建&#xff0c;如自动化测试中执行test、stg、prod环境的构建&#xff0c;Jenkins是支持参数化构建的。 以下是Jenkins官…

kaggle量化赛金牌方案(第七名解决方案)(下)

— 无特征工程的神经网络模型&#xff08;得分 5.34X&#xff09; 比赛进入最后阶段&#xff0c;现在是时候深入了解一些关于神经网络模型的见解了。由于 Kaggle 讨论区的需求&#xff0c;我在这里分享两个神经网络模型。第一个是 LSTM 模型&#xff0c;第二个是卷积网络&…

pmp顺利通关总结

目录 一、背景二、总结三、过程 一、背景 人活着总是想去做一些事情&#xff0c;通过这些事情来证明自己还活着。 而我证明自己还会活着并且活得很好的方式和途径&#xff0c;是通过这些东西去让自己有一个明确的边界节点&#xff1b;借此知识来验证自己的学习能力。 我坚定认…

汇凯金业:投资交易如何才能不亏损

投资交易中永不亏损是一个理想化的目标&#xff0c;现实中无法完全避免亏损。然而&#xff0c;通过科学的方法、合理的策略和严格的风险管理&#xff0c;投资者可以大幅减少亏损&#xff0c;并提高长期盈利的概率。以下是一些关键策略和方法&#xff0c;帮助投资者在交易中尽量…