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

news2024/11/18 21:38:18

        在使用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.coloradmin.cn/o/1890764.html

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

相关文章

【Linux】线程——线程的概念、线程的特点、线程的优点和缺点、线程和进程、线程函数的使用

文章目录 Linux线程1. 线程的概念1.1 什么是线程 2. 线程的特点2.1 线程的优点2.2 线程的缺点2.4 线程和进程 3. 线程函数的使用pthread_create() 创建线程pthread_self() 获取线程IDpthread_exit() 线程终止pthread_cancel() 线程取消pthread_join() 线程等待pthread_detach()…

使用Redis实现消息队列:List、Pub/Sub和Stream的实践

摘要 Redis是一个高性能的键值存储系统&#xff0c;它的多种数据结构使其成为实现消息队列的理想选择。本文将探讨如何使用Redis的List、Pub/Sub和Stream数据结构来实现一个高效的消息队列系统。 1. 消息队列的基本概念 消息队列是一种应用程序之间进行通信的机制&#xff0…

docker容器间网络仿真工具-pumba

docker-tc&pumba docker-tc:docker-tc项目仓库 pumba:pumba项目仓库 这两个项目理论上都可以实现对容器间的网络环境进行各种模拟干预&#xff0c;包括延迟&#xff0c;丢包&#xff0c;带宽限制等。 但是我在实际使用时&#xff0c;发现docker-tc这个工具在进行网络进行模…

Docker 部署 Minio 对象存储服务器

文章目录 Github官网文档简介dockerdocker-compose.ymlmc 客户端mc 基础命令Golang 示例创建 test 账号密钥文件上传示例 Github https://github.com/minio/minio 官网 https://min.io/https://www.minio.org.cn/ 文档 https://www.minio.org.cn/docs/minio/kubernetes/up…

摸爬滚打半年,我是如何从小白进阶到渗透测试工程师

前言 工作也好几年了&#xff0c;在这摸爬滚打中&#xff0c;遇到了服务器被黑&#xff0c;网站被人DDOS攻击&#xff0c;数据库被篡改等等。服务器也不是你说不让人上就不让人上的&#xff0c;所以IT安全这个话题还是比较沉重的&#xff0c;涉及的东西很多&#xff0c;只有你…

个人博客|PHP源码|支持多国语言切换

一. 前言 今天小编给大家带来了一款可学习&#xff0c;可商用的&#xff0c;支持多国语言的个人博客网站源码&#xff0c;支持二开&#xff0c;无加密。此博客相当简洁&#xff0c;也适合海外。详细界面和功能见下面视频演示。 如果您正好有此需求源码&#xff0c;请联系小编…

SSM学习4:spring整合mybatis、spring整合Junit

spring整合mybatis 之前的内容是有service层&#xff08;业务实现层&#xff09;、dao层&#xff08;操作数据库&#xff09;&#xff0c;现在新添加一个domain&#xff08;与业务相关的实体类&#xff09; 依赖配置 pom.xml <?xml version"1.0" encoding&quo…

一篇文章搞懂弹性云服务器和轻量云服务器的区别

前言 在众多的云服务器类型中&#xff0c;弹性云服务器和轻量云服务器因其各自的特点和优势&#xff0c;受到了广大用户的青睐。那么&#xff0c;这两者之间到底有哪些区别呢&#xff1f;本文将为您详细解析。 弹性云服务器&#xff1a;灵活多变的计算资源池 弹性云服务器&…

鸿蒙开发设备管理:【@ohos.sensor (传感器)】

传感器 说明&#xff1a; 本模块首批接口从API version 8开始支持。后续版本的新增接口&#xff0c;采用上角标单独标记接口的起始版本。 导入模块 import sensor from ohos.sensor;sensor.on ACCELEROMETER on(type: SensorType.SENSOR_TYPE_ID_ACCELEROMETER, callback: C…

04-ArcGIS For JavaScript的可视域分析功能

文章目录 综述代码实现代码解析结果 综述 在数字孪生或者实景三维的项目中&#xff0c;视频融合和可视域分析&#xff0c;一直都是热点问题。Cesium中&#xff0c;支持对阴影的后处理操作&#xff0c;通过重新编写GLSL代码就能实现视域和视频融合的功能。ArcGIS之前支持的可视…

Vue+Xterm.js+WebSocket+JSch实现Web Shell终端

一、需求 在系统中使用Web Shell连接集群的登录节点 二、实现 前端使用Vue&#xff0c;WebSocket实现前后端通信&#xff0c;后端使用JSch ssh通讯包。 1. 前端核心代码 <template><div class"shell-container"><div id"shell"/>&l…

day01-切片和索引

day01-切片和索引 ndarray对象的内容可以通过索引或切片来访问和修改&#xff0c;与 Python 中list 的切片操作一样。 ndarray数组可以基于0-n的下标进行索引 注意&#xff0c;数组切片并不像列表切片会重新开辟一片空间&#xff0c;而是地址引用&#xff0c;需要使用.copy()…

【Threejs进阶教程-着色器篇】2. Uniform的基本用法与Uniform的调试

Uniform的基本用法与Uniform的调试 关于本Shader教程优化上一篇的效果优化光栅栏高度让透明度和颜色变的更平滑pow()函数借助数学工具更好的理解函数 Unifoms简介编写uniforms修改片元着色器代码借助lil.gui调试uniforms使用uniform控制颜色继续在uniforms添加颜色在着色器中接…

动态住宅代理IP的3个优点

在大数据时代的背景下&#xff0c;代理IP成为了很多企业顺利开展的重要工具。代理IP地址可以分为住宅代理IP地址和数据中心代理IP地址。选择住宅代理IP的好处是可以实现真正的高匿名性&#xff0c;而使用数据中心代理IP可能会暴露自己使用代理的情况。 住宅代理IP是指互联网服务…

JavaScript中location对象的主要属性和方法

属性 href&#xff1a;获取或设置整个URL。protocol&#xff1a;获取URL的协议部分&#xff0c;如"http:"或"https:"。host&#xff1a;获取URL的主机名&#xff08;包括端口号&#xff0c;如果有的话&#xff09;。hostname&#xff1a;获取URL的主机名&…

Android studio 打包低版本的Android项目报错

一、报错内容 Execution failed for task :app:packageRelease. > A failure occurred while executing com.android.build.gradle.internal.tasks.Workers$ActionFacade> com.android.ide.common.signing.KeytoolException: Failed to read key key0 from store "…

【Portswigger 学院】路径遍历

路径遍历&#xff08;Path traversal&#xff09;又称目录遍历&#xff08;Directory traversal&#xff09;&#xff0c;允许攻击者通过应用程序读取或写入服务器上的任意文件&#xff0c;例如读取应用程序源代码和数据、凭证和操作系统文件&#xff0c;或写入应用程序所访问或…

10 Posix API与网络协议栈

POSIX概念 POSIX是由IEEE指定的一系列标准,用于澄清和统一Unix-y操作系统提供的应用程序编程接口(以及辅助问题,如命令行shell实用程序),当您编写程序以依赖POSIX标准时,您可以非常肯定能够轻松地将它们移植到大量的Unix衍生产品系列中(包括Linux,但不限于此!)。 如…

奇瑞被曝强制加班,“896”成常态且没有加班费

ChatGPT狂飙160天&#xff0c;世界已经不是之前的样子。 更多资源欢迎关注 7 月 2 日消息&#xff0c;一位认证为“奇瑞员工”的网友近期发帖引发热议&#xff0c;奇瑞汽车内部存在强制加班行为&#xff0c;每周加班时长需大于 20 小时并且没有加班费&#xff0c;仅补贴 10 元…

人口萎缩,韩国釜山“进入消失阶段”

KlipC报道&#xff1a;调查显示&#xff0c;随着低生育率和人口老化&#xff0c;釜山人口逐渐萎缩&#xff0c;韩国第二大城市釜山显现出“进入消失阶段”的迹象。 据悉&#xff0c;“消失风险指数”是将20岁至39岁女性人口总数除以65岁及以上人口得到的数值。当该指数大于1.5…