refactor(OperationColumn): 重构动态宽度计算的操作列组件

- 用更动态的方法代替静态宽度计算
- 优化计算逻辑代码
This commit is contained in:
XFeng committed 2026-01-13 18:03:47 +08:00
1 parent 15fe2c2328
commit cc8560a048
1 file changed
+40 -58
+40 -58
View File
@@ -1,28 +1,29 @@
<template> <template>
<el-table-column <el-table-column :prop :label :fixed :align :show-overflow-tooltip :width="finalWidth">
:label="label"
:fixed="fixed"
:align="align"
:show-overflow-tooltip="showOverflowTooltip"
:width="finalWidth"
>
<template #default="{ row }"> <template #default="{ row }">
<div v-auto-width class="operation-buttons"> <div v-auto class="operation-button">
<slot :row="row"></slot> <slot :row="row" />
</div> </div>
</template> </template>
</el-table-column> </el-table-column>
</template> </template>
<script setup lang="ts"> <script lang="ts" setup>
interface Props { interface Props {
/**
* 表格数据长度
* 用于性能优化,避免多次计算宽度
*/
listDataLength: number; listDataLength: number;
prop?: string; prop?: string;
label?: string; label?: string;
fixed?: string; fixed?: string;
align?: string; align?: string;
width?: number;
showOverflowTooltip?: boolean; showOverflowTooltip?: boolean;
/**
* 最小宽度,优先级高于自动计算宽度,默认80px
* @default 80px
*/
minWidth?: number; minWidth?: number;
} }
@@ -30,62 +31,43 @@ const props = withDefaults(defineProps<Props>(), {
label: "操作", label: "操作",
fixed: "right", fixed: "right",
align: "center", align: "center",
minWidth: 80,
}); });
const count = ref(0); const count = ref(0);
const operationWidth = ref(props.minWidth || 80); const maxWidth = ref(80);
// 霈∠��滢��堒捐摨?
const calculateWidth = () => { const calculateWidth = () => {
count.value++; count.value++;
if (count.value !== props.listDataLength) return; if (count.value !== props.listDataLength) return;
const maxWidth = getOperationMaxWidth();
operationWidth.value = Math.max(maxWidth, props.minWidth); let totalWidth = 0;
maxWidth.value = 80; // 重置为初始值
const els = document.getElementsByClassName("operation-button");
Array.from(els).forEach((el) => {
const buttons = el.querySelectorAll(".el-button");
totalWidth = Array.from(buttons).reduce((prev, button) => {
// 14 是按钮之间的距离
// 组成:按钮的左边距(Element Plus默认为12px)+按钮的padding(Element Plus默认为2px)
return prev + button.scrollWidth + 14;
}, 24); // 24 是左右内边距
maxWidth.value = Math.max(maxWidth.value, totalWidth);
});
count.value = 0; count.value = 0;
}; };
// 霈∠���蝏�捐摨? const vAuto = {
mounted: () => {
// 初次挂载的时候计算一次
calculateWidth();
},
updated: () => {
// 数据更新时重新计算一次
calculateWidth();
},
};
const finalWidth = computed(() => { const finalWidth = computed(() => {
return props.width || operationWidth.value || props.minWidth; return props.minWidth || maxWidth.value;
}); });
// �芷���摰賢漲��誘
const vAutoWidth = {
mounted() {
// �脲活��蝸��𧒄�躰恣蝞𦯀�甈?
calculateWidth();
},
updated() {
// �唳旿�湔鰵�園��啗恣蝞𦯀�甈?
calculateWidth();
},
};
/**
* �瑕��厰僼�圈���捐撣行䔉�瑕��滢�蝏����憭批捐摨?
* 瘜冽�雿輻鍂�園�閬�蝙�?`class="operation-buttons"` ���蝑曉�鋆寞�雿𨀣��?
* @returns {number} 餈𥪜��滢�蝏����憭批捐摨?
*/
const getOperationMaxWidth = () => {
const el = document.getElementsByClassName("operation-buttons");
// �𡝗�雿𦦵����憭批捐摨?
let maxWidth = 0;
let totalWidth: any = 0;
Array.prototype.forEach.call(el, (item) => {
// �瑕�瘥譍葵item��om
const buttons = item.querySelectorAll(".el-button");
// �瑕�瘥讛��厰僼���餃捐摨?
totalWidth = Array.from(buttons).reduce((acc, button: any) => {
return acc + button.scrollWidth + 22; // 瘥譍葵�厰僼��捐摨血�銝𢠃��坔捐摨?
}, 0);
// �瑕���憭抒�摰賢漲
if (totalWidth > maxWidth) maxWidth = totalWidth;
});
return maxWidth;
};
</script> </script>