vue完美实现el-table列宽自适应

背景

Element UI 是 PC 端比较流行的 Vue.js UI 框架,它的组件库基本能满足大部分常见的业务需求。但有时候会有一些定制性比较高的需求,组件本身可能没办法满足。最近在项目里就碰到了。

很多页面都需要用到表格组件el-table。如果没有给el-table-column指定宽度,默认情况下会平均分配给剩余的列。在列数比较多的情况,如果el-table宽度限定在容器内,单元格里的内容就会换行。强制不换行,内容要么在单元格内滚动,要么就会溢出或被截断。

产品想要的效果是:内容保持单行显示,列间距保持一致,表格超出容器允许水平滚动。el-table-column是支持设置固定宽度的,在内容宽度可预知的情况下,也能满足这个需求。问题就在于如何让列宽动态适应内容的宽度。在官方文档也没找到这样的选项,应该是组件本身不支持。

技术方案

于是想到了动态计算内容宽度的方案。网上也有人提过这个思路,做法是根据内容字符数来计算宽度。这种方法有几个局限:

  • 内容必须是文本
  • 不同字符宽度不一,结算结果不够准确
  • 需要在渲染前操作数据,不利于解耦

我采用了另一种思路,还是动态计算内容宽度,但是根据实际渲染后的 DOM 元素宽度,这样就能解决上面三个问题。

具体怎么做呢?通过查看渲染后的 DOM 元素发现,el-table 的表头和内容分别用了一个原生table,通过colgroup设置每列的宽度。就从这里入手,col的name属性值和对应的 td的class值是一致的,这样就可以遍历对应列的所有单元格,找出宽度最大的单元格,用它的内容宽度加上一个边距作为该列的宽度。

具体实现

怎么计算内容宽度呢?这是个比较关键的步骤。渲染后的每个单元格有个.cell类,用white-space: nowrap; overflow: auto;设置为不允许换行,内容超出后可滚动,同时设置display: inline-block;以便计算实际内容宽度。这样,最终的宽度可通过.cell元素的scrollWidth属性得到。

function adjustColumnWidth(table) {
  const colgroup = table.querySelector("colgroup");
  const colDefs = [...colgroup.querySelectorAll("col")];
  colDefs.forEach((col) => {
    const clsName = col.getAttribute("name");
    const cells = [
      ...table.querySelectorAll(`td.${clsName}`),
      ...table.querySelectorAll(`th.${clsName}`),
    ];
    // 忽略加了"leave-alone"类的列
    if (cells[0]?.classList?.contains?.("leave-alone")) {
      return;
    }
    const widthList = cells.map((el) => {
      return el.querySelector(".cell")?.scrollWidth || 0;
    });
    const max = Math.max(...widthList);
    const padding = 32;
    table.querySelectorAll(`col[name=${clsName}]`).forEach((el) => {
      el.setAttribute("width", max + padding);
    });
  });
}

中间的探索过程比较繁琐,但最终的代码实现却非常简洁。在什么时候触发列宽计算呢?自然是组件渲染完成后。为了方便重用,我采用了 Vue 自定义指令的方式。

Vue.directive("fit-columns", {
  update() {},
  bind() {},
  inserted(el) {
    setTimeout(() => {
      adjustColumnWidth(el);
    }, 300);
  },
  componentUpdated(el) {
    el.classList.add("r-table");
    setTimeout(() => {
      adjustColumnWidth(el);
    }, 300);
  },
  unbind() {},
});

更进一步,我封装了一个 Vue 插件叫v-fit-columns,已经发布到 npm 仓库,直接安装即可使用。
安装:

npm install v-fit-columns --save

引入:

import Vue from 'vue';
import Plugin from 'v-fit-columns';
Vue.use(Plugin);

使用:

<el-table v-fit-columns>
  <el-table-column label="No." type="index" class-name="leave-alone"></el-table-column>
  <el-table-column label="Name" prop="name"></el-table-column>
  <el-table-column label="Age" prop="age"></el-table-column>
</el-table>

源码仓库在这:https://github.com/kaysonli/v-fit-columns ,欢迎各位不吝赐教和 Star!

总结

这个方案多少有点 Hack 的意味,只顾实现需求,可能在其他方面还有点瑕疵,比如渲染完后会稍微闪一下(因为要重新调整宽度,会出现 reflow)。不过从最终实现的效果来看,还算令人满意

以上就是vue完美实现el-table列宽自适应的详细内容,更多关于vue实现el-table列宽自适应的资料请关注我们其它相关文章!

(0)

相关推荐

  • VUE2.0+ElementUI2.0表格el-table循环动态列渲染的写法详解

    先看看ElementUI里关于el-table的template数据结构: <template> <el-table :data="tableData" style="width: 100%"> <el-table-column prop="date" label="日期" width="180"> </el-table-column> <el-tabl

  • vue+element获取el-table某行的下标,根据下标操作数组对象方式

    1.在vue中对数组中的某个对象进行操作时(替换.删除),都需要用到该对象在数组中的下标. 前端代码: scope.$index :获取当前行的下标 scope.row:获取当前行的对象 效果图: 思路:通过点击事件将该对象在数组中的下标传递到方法中,然后对数组进行操作 即可根据下标删除数组中对应的对象. 补充知识:vue-element-upload 文件上传打开选择文件弹框前进行提示或操作 在项目中使用文件上传功能时,需求是不能直接弹出弹框,要先二次确认或进行提示.引申开来,即可在打开选择文

  • VUE2.0 ElementUI2.0表格el-table自适应高度的实现方法

    在开发中,需要表格控件根据浏览器高度进行调整,固定表头,且然后多余的出滚动条,官方给出的: 只要在el-table元素中定义了height属性,即可实现固定表头的表格,而不需要额外的代码. 然后直接上template代码: <template> <el-table :data="tableData3" height="250" border style="width: 100%"> <el-table-column

  • vue 使用 sortable 实现 el-table 拖拽排序功能

    本文给大家介绍vue 使用 sortable 实现 el-table 拖拽排序功能,具体内容如下所示: npm 下载: npm install sortablejs --save 引入: import Sortable from "sortablejs"; 代码: <template> <div class="table"> <el-table ref="dragTable" :data="tableDat

  • vue el-table实现自定义表头

    本文实例为大家分享了vue el-table实现自定义表头的具体代码,供大家参考,具体内容如下 el-table可以通过设置 Scoped slot 来实现自定义表头. 文档说明如下: 代码实现: <template> <el-dialog width="50%" :visible.sync="isShow" :before-close="beforeClose" title="自定义设备类型属性">

  • 详解VUE 对element-ui中的ElTableColumn扩展

    公司有一个新的需求,点击ElTableColumn的头部可以进行搜索,这个功能同事已经做出来了,但是使用有些不方便,自己就打算封装成一个组件,学习一下. ElTableColumn本来是这个样子的: 要做成的是这个样子: 我直接就放代码了,挨着挨着说明太多了. 代码的结构: 组件 <!-- ElTableColumnPro.vue --> <template> <el-table-column v-if="visible" :formatter="

  • vue修改Element的el-table样式的4种方法

    修改Element中的el-table样式,可以使用以下几种方法: 1. row-style 行的 style 的回调方法,也可以使用一个固定的 Object 为所有行设置一样的 Style. 2. cell-style 单元格的 style 的回调方法,也可以使用一个固定的 Object 为所有单元格设置一样的 Style. 3. header-row-style 表头行的 style 的回调方法,也可以使用一个固定的 Object 为所有表头行设置一样的 Style. 4. header-c

  • vue2.0 + element UI 中 el-table 数据导出Excel的方法

    1.安装相关依赖 主要是两个依赖 npm install --save xlsx file-saver 如果想详细看着两个插件使用,请移步github. https://github.com/SheetJS/js-xlsx https://github.com/eligrey/FileSaver.js 2.组件里头引入 import FileSaver from 'file-saver' import XLSX from 'xlsx' 3.组件methods里写一个方法 exportExcel

  • vue el-table实现行内编辑功能

    最近做一个vue前后端分离的项目,前端框架用element ui,在 使用 el-table 的过程中,需要实现行内编辑,效果大概是这样: 分为下面几个步骤: (1) 自定义 el-table 的表头(即添加 "新增" 按钮): <el-table :data="propTableData.col.filter(data => handleAdd || data.name.toLowerCase().includes(handleAdd.toLowerCase()

  • VUE2.0+ElementUI2.0表格el-table实现表头扩展el-tooltip

    ElementUI2.0的表格的扩展: elementUI表格table elementUI文字提示Tooltip 如果要实现鼠标移到表头有注释或者弹框该怎么添加呢? <el-table empty-text="正在加载中..." :data="contentList" style="width: 100%" @sort-change="sort" class="pro-table-item" too

随机推荐