效果演示
lilu0826.github.io/el-table-au…
el-table自适应列宽实现思路
- 获取某一个列的所有单元格dom
- 为该列的所有单元格设置width:fit-content
- 计算所有单元格的宽度
- 取出最大单元格的宽度
- 更新该列的宽度
获取某列的所有单元格
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…