el-table-column 表格列宽度根据内容自适应

问题

el-table 对于动态获取数据的表格,希望单元格内容不换行,就要设定足够的宽度,el-table-column 是支持设置固定宽度的,但是,由于数据不确定,所以无法预设宽度,怎么解决呢?

解决方案

可以根据实际渲染后的 DOM 元素宽度动态计算内容宽度就能设置列的宽度。

具体做法

通过查看渲染后的 DOM 元素发现,el-table 的表头和内容分别用了一个原生table,通过colgroup设置每列的宽度。就从这里入手,col的name属性值和对应的 td 的class值是一致的,这样就可以遍历对应列的所有单元格,找出宽度最大的单元格,用它的内容宽度加上一个边距作为该列的宽度。
el-table-column 表格列宽度根据内容自适应_第1张图片
el-table-column 表格列宽度根据内容自适应_第2张图片
思路:
首先要获取列内容的宽度,就需要内容不换行一行展示。通过查看渲染后的 DOM 元素发现,每个单元格有个.cell类,用white-space: nowrap; overflow: auto;display: inline-block;设置不允许换行,以便计算实际内容宽度。最终的宽度可通过.cell元素的scrollWidth属性得到。

在某个全局引入的scss文件写入:

// td,th的 cell 都需要设置
//(注意:一旦全局设置了这些样式,所有的表格内容都将不换行)
.el-table .cell, .el-table th > .cell {
  display: inline-block;
  white-space: nowrap;
  width: auto;
  overflow: auto;
}
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 = 20;
      table.querySelectorAll(`col[name=${clsName}]`).forEach((el) => {
        el.setAttribute("width", max + padding);
      });
    });
  }

为了方便重用,采用了 Vue 自定义指令的方式。

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

自定义指令注册完成,只需要在表格里使用就可以了

<el-table v-fitColumns>
	<el-table-column label="name" prop="name"></el-table-column>
</el-table>

还没完…测试此功能时表格你会发现一个边界问题:当没有用v-fitColumns指令时,列数较少并且列内容发生换行的表格刚好满屏展示,底部不需要滚动条,但使用v-fitColumns指令后列内容不换行造成溢出表格,需要底部滚动条时,你会发现并没有滚动条,无法滚动,溢出部分无法查看,此时查看 DOM 元素发现问题所在,是因为第一次表格渲染样式为不可滚动,如下图所示。
el-table-column 表格列宽度根据内容自适应_第3张图片

如下解决办法:

// 此段代码放入 adjustColumnWidth 内部最后面即可。
const scrollingBody = table.querySelectorAll("div.is-scrolling-none");
if(scrollingBody[0]?.classList?.contains?.("is-scrolling-none")) {
  scrollingBody[0].classList.remove("is-scrolling-none");
  scrollingBody[0].classList.add("is-scrolling-left");
  scrollingBody[0].style.overflowX = "auto";
}

实现效果展示:
在这里插入图片描述

参考链接:https://www.cnblogs.com/lzkwin/p/13575805.html

你可能感兴趣的:(实例,vue,elementui)