el-table的列宽自适应实现

947 阅读2分钟

效果演示

lilu0826.github.io/el-table-au…

el-table自适应列宽实现思路

  1. 获取某一个列的所有单元格dom
  2. 为该列的所有单元格设置width:fit-content
  3. 计算所有单元格的宽度
  4. 取出最大单元格的宽度
  5. 更新该列的宽度

获取某列的所有单元格

el-table里面有一个store属性,在里面可以获取到所有的columns数组

_elTableRef.value.store.states.columns.value

可以根据列设置的prop找到该列的column

const column = _elTableRef.value.store.states.columns.value.find(
        (el) => el.property == "address"
    );

column对象上有一个名叫id的属性,该id属性会被设置到该列单元格的class上面,我们可以借助此来查询所有单元格

//拿到该列单元格
  const tds = _elTableRef.value.$el.querySelectorAll(`.${column.id}>.cell`);

计算该列单元格的最大宽度

准备一个css类,叫做testElementSize

<style>
.testElementSize {
    min-width: fit-content !important;
    width: fit-content !important;
    height: auto !important;
    overflow: auto !important;
    white-space: nowrap !important;
    text-overflow: unset !important;
}
</style>

循环遍历该单元格,计算其内容宽度(此写法有布局抖动,性能很差推荐下面的新写法)

//拿到单元格内容宽度
    const tdWidths = [...tds].map((element) => {
        element.classList.add("testElementSize");
        const width =
            element.getBoundingClientRect().width || element.scrollWidth;
        element.classList.remove("testElementSize");
        //这里+2是因为element的表格可能有左右边框两个像素
        console.log("width", width);
        return Math.ceil(width) + 2;
    });

循环遍历该单元格,计算其内容宽度,新写法无布局抖动

const tdWidths = [...tds]
        .map((element) => {
            element.classList.add("testElementSize");
            return element;
        })
        .map((element) => {
            const width =
                element.getBoundingClientRect().width || element.scrollWidth;
            //这里+2是因为element的表格可能有左右边框两个像素
            return {element, width:Math.ceil(width) + 2};
        })
        .map(({element, width}) => {
            element.classList.remove("testElementSize");
            return width;
        });

算出最大单元格内容的宽度

//最大的单元格宽度
    let maxWidth = Math.max(...tdWidths);

更新该列的宽度

这里是查看并借鉴了el-table列拖动后更新宽度的代码

    //设置该列宽度并更新布局
    column.realWidth = maxWidth;
    column.width = maxWidth;
    requestAnimationFrame(() => {
        _elTableRef.value.doLayout();
    });

总结

直接取表格单元格进行计算,其列宽算出来比较准确,当自定义列渲染时,比如操作列渲染的是一些按钮时,也可以准确计算。

该计算方式会引起布局抖动,性能较差,不知道有没有大佬有优化建议的 已更新无布局抖动写法

完整源代码放到了github上了:github.com/lilu0826/el…