系列
需求
- 给 Table 头 排序事件 加防抖
- 自适应宽度,上限200px,超过允许两行带省略号显示,增加防抖
给 Table 头 排序事件 加防抖
import Vue from "vue";
import { debounce } from "lodash";
import { Table } from "element-ui";
const elTableHack = {
install: (Vue) => {
//ElementUI排序回调添加防抖
const handleSortClick =
Table.components.TableHeader.methods.handleSortClick;
Object.assign(Table.components.TableHeader.methods, {
//此方法为排序触发的事件,添加防抖,和search频率同步,
handleSortClick: debounce(
function (...args) {
//调用原方法
handleSortClick.apply(this, args);
//模拟一个body上的点击事件,主动触发body上的委托 ,触发el-popover等组件的关闭
document.querySelector("body").click();
},
300,
{
leading: true,
trailing: false,
}
),
});
Vue.use(Table);
},
};
Vue.use(elTableHack);
自适应宽度,上限200px,超过允许两行带省略号显示
错误实例:
分析:
- 表格宽度需要根据 table 实际内容填充后再计算宽度
- 每列中获取最大长度的cell,先用canvas获取宽度,再用双行样式比较宽度,得出最大宽度
方法: table源码关于列宽度计算的代码 node_modules\element-ui\packages\table\src\table-layout.js updateColumnsWidth 函数,拷贝整个 updateColumnsWidth 函数,在红框处扩展
import Vue from "vue";
import { debounce, throttle } from "lodash";
import { Table, TableColumn } from "element-ui";
const elTableHack = {
install: (Vue) => {
// 设置最大宽度参数
Object.assign(TableColumn, {
mixins: [
{
props: {
maxWidth: {
type: Number,
default: 200,
},
},
mounted() {
this.columnConfig.maxWidth = this.maxWidth;
},
},
],
});
// 转canvas计算dom宽度
function getTextWidth(text, font = "12px") {
var canvas =
getTextWidth.canvas ||
(getTextWidth.canvas = document.createElement("canvas"));
var context = canvas.getContext("2d");
context.font = font;
var metrics = context.measureText(text);
return metrics.width;
}
Object.assign(Table.mixins, [
...Table.mixins,
{
watch: {
data() {
this.layout.updateColumnsWidth();
this.$nextTick(() => {
this.layout.updateElsHeight();
});
},
},
mounted() {
const that = this;
this.layout.updateColumnsWidth = throttle(
function () {
/* 原来updateColumnsWidth部分
* let flexColumns = flattenColumns.filter(
* (column) => typeof column.width !== "number"
* );
*/
/*** .... */
/** 增加下面部分*/
flexColumns.forEach((column) => {
let minWidth = 0;
let width = 0;
let maxWidth = 200;
if (column) {
minWidth = parseFloat(column.minWidth) || 0;
width = parseFloat(column.width) || 0;
maxWidth = parseFloat(column.maxWidth) || 200;
}
if (width) {
return;
}
const cells = [
...that.$el.querySelectorAll(`td.${column.id}`),
...that.$el.querySelectorAll(`th.${column.id}`),
];
/** 当前列最大cell */
const maxCell = cells.reduce(
(pre, cell) => {
const text = cell.innerText.replace(/\s/g, "");
const textWidth = getTextWidth(text);
if (textWidth > pre.textWidth) {
pre.text = text;
pre.cell = cell;
pre.textWidth = textWidth;
}
return pre;
},
{
cell: null,
text: "",
textWidth: 0,
}
);
let res = 0;
if (maxCell.cell) {
maxCell.cell.classList.add("for-count-cell");
res = (maxCell.cell.scrollWidth || 0) + 20;
maxCell.cell.classList.remove("for-count-cell");
}
const max = Math.max(res, minWidth);
const dist = Math.min(maxWidth, max);
column.minWidth = dist;
});
/* 原来updateColumnsWidth部分
*flattenColumns.forEach((column) => {
* if (typeof column.width === 'number' && column.realWidth) column.realWidth = null;
*});
*/
/*** .... */
}.bind(this.layout),
100
);
},
},
]);
Vue.use(Table);
},
};
Vue.use(elTableHack);
- 全局css
<style>
/** 用于不换行计算最大宽度 */
.for-count-cell {
display: inline-block !important;
white-space: nowrap !important;
width: auto !important;
overflow: auto !important;
}
/** 最多两行 */
.el-table__cell .cell {
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
display: -webkit-box;
font-weight: 400;
overflow: hidden;
text-align: center;
text-overflow: ellipsis;
}
</style>
效果对比
- 没有自适应宽度较宽,效果比较差
- 添加自适应宽度 最大200 且最多两行,效果较好