一、自定义指令
* 创建table-auto-height.ts 文件*
import {h, nextTick, render} from "vue";
import {ElTable, ElTableColumn} from "element-plus";
export default (app: any) => {
//自定义组件
app.directive('table-auto-height', {
async created(el: any, binding: any, vnode, prevVnode) {
let tableCol = [];
//组合table
for (const appElement of vnode.dynamicChildren[0].children) {
//获取表头 及其 原有插槽
tableCol.push({props: appElement.props, children: appElement.children})
}
await creatTable(tableCol, el, binding);
}
}
)
}
const getNextSiblings = (element: any) => {
let siblings = [];
while (element.nextElementSibling) {
element = element.nextElementSibling;
if (element.nodeType === 1 && element !== document.body) {
siblings.push(element);
}
}
return siblings;
}
const getPreviousSiblings = (element: any) => {
let siblings = [];
while (element.previousElementSibling) {
element = element.previousElementSibling;
if (element.nodeType === 1 && element !== document.body) {
siblings.push(element);
}
}
return siblings;
}
const extractedNumber = (str) => {
const match = str.match(/\d+(\.\d+)?/);
return match ? parseFloat(match[0]) : 0;
}
const creatTable = async (columns, el, binding) => {
//默认存在一个元素用来动态计算pagesizs
const tableData = [{}]
const colunsSolt = (column) => {
let result = {};
if (column.children) {
result = column.children;
}
if (column.childColumns) {
result = {default: () => createColumns(column.childColumns)}
}
return result;
}
const createColumns = (columns) => {
if (!columns.length) return undefined
return columns.map(column => {
return h(ElTableColumn, {...column.props,show:false},
colunsSolt(column)
)
})
}
let div = document.createElement("div");
div.id = Math.random().toString(36).slice(-6);
let eltableVnode = h(ElTable, {
data: tableData
}, () => createColumns(columns)
);
render(eltableVnode, div)
el.appendChild(div)
//必须为两个await await 确保 eltable 完全渲染之后 在执行以下代码 防止获取table高度不正确
await await nextTick();
let eltableDom = document.getElementById(div.id);
// 获取表头高度
let hiddenHeaderHeight=eltableDom.querySelector(".el-table__header").getBoundingClientRect().height;
let tableHeaderHeightPx = window.getComputedStyle(eltableDom.querySelector(".el-table__header")).height;
let tableHeaderHeight = extractedNumber(tableHeaderHeightPx)
//获取行高度el-table__body > el-table__row
let tableBodyTrHeightPx = window.getComputedStyle(eltableDom.querySelector(".el-table__body .el-table__row")).height;
let tableBodyTrHeight = extractedNumber(tableBodyTrHeightPx)
let clientHeight = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
let nextSiblings = getNextSiblings(el);
let previousSiblings = getPreviousSiblings(el)
let result = [...nextSiblings, ...previousSiblings];
result.forEach(res => {
clientHeight -= res.clientHeight;
})
let pageSize = Math.floor((clientHeight - tableHeaderHeight) / tableBodyTrHeight)
binding.value.pageSize = pageSize
el.style.height = pageSize * tableBodyTrHeight + tableHeaderHeight + "px";
div.style.display = "none"
}
二、全局指令注册
main.ts 注册全局指令
const app = createApp(App)
import tableAutoHeight from "@/directive/table-auto-height.ts";
tableAutoHeight(app)
三、组件使用
<template>
<el-table :data="tableData" stripe v-table-auto-height:pagination="pagination" show-overflow-tooltip >
<el-table-column type="index" min-width="55" label="序号"/>
</el-table>
</template>
<script setup lang="ts">
import { onMounted, reactive} from "vue";
onMounted(() => {
await await nextTick()
searchForm(1)
})
let pagination = reactive({
pageSize: 0,
pageNum: 1
})
let tableData = reactive([]) as any;
const searchForm = (num: any) => {
console.log(pagination.pageSize)
}
</script>