From 8fc90c168ec3518345a0e294fc0065c59622fe96 Mon Sep 17 00:00:00 2001 From: hechang27-sprt Date: Tue, 31 Mar 2026 16:04:41 +0800 Subject: [PATCH] WIP: optimize resize performance --- packages/base/data/list-table-v2.vue | 32 +++++++++++++++++++++------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/packages/base/data/list-table-v2.vue b/packages/base/data/list-table-v2.vue index e01c004..a760f9c 100644 --- a/packages/base/data/list-table-v2.vue +++ b/packages/base/data/list-table-v2.vue @@ -121,6 +121,7 @@ const miniTableData = ref([]); const estimatedRowHeight = ref(undefined); const estimatedHeaderHeight = ref(undefined); let miniTableResizeObserver: ResizeObserver | null = null; +let lastMiniTableHeight = 0; // Header height constant @@ -170,6 +171,7 @@ interface Props { columns?: ListTableColumn[]; page?: boolean; height?: number | string; + minHeight?: number | string; maxHeight?: number | string; example?: any; rowKey?: string; @@ -189,6 +191,7 @@ const prop = withDefaults(defineProps(), { columns: () => [], page: false, height: undefined, + minHeight: 300, maxHeight: undefined, example: () => ({}), rowKey: "id", @@ -261,6 +264,8 @@ watch( if (rowHeight && rowHeight > 0) { estimatedRowHeight.value = rowHeight; } + // Update last known mini-table height for ResizeObserver comparison + lastMiniTableHeight = miniTableRef.value?.offsetHeight || 0; }, { immediate: true } ); @@ -276,13 +281,23 @@ function estimateTableRowHeight() { return { headerHeight, rowHeight }; } -// Setup ResizeObserver on mount (not window resize - that causes flickering) +// Setup ResizeObserver on mount +// Observe miniTableRef instead of myTableRef - only re-probe if mini-table's rendered height changes +// This avoids unnecessary re-probing during window resize when container width changes but row heights stay same onMounted(() => { - // Resize handler - measure first, then clear and set in same microtask + // Resize handler - only re-probe if the mini-table's actual height changed const handleResize = lodash.debounce(async () => { if (!shouldUseProbeRow.value || miniTableData.value.length === 0) { return; } + + // Check if mini-table height actually changed (e.g., due to text wrapping) + const currentHeight = miniTableRef.value?.offsetHeight || 0; + if (currentHeight === lastMiniTableHeight) { + return; // Height unchanged, no need to re-probe + } + lastMiniTableHeight = currentHeight; + await nextTick(); await new Promise((resolve) => requestAnimationFrame(resolve)); await new Promise((resolve) => requestAnimationFrame(resolve)); @@ -300,16 +315,17 @@ onMounted(() => { estimatedRowHeight.value = newRow; estimatedHeaderHeight.value = newHeader; }); - }, 50); + }, 200); - // Use ResizeObserver on .my-table to detect width changes - // This is better than window resize because it only fires when OUR container changes + // Observe miniTableRef for height changes + // The mini-table's height only changes when column widths cause text to wrap + // During typical window resize with fixed-height content, height stays same → no re-probe miniTableResizeObserver = new ResizeObserver(() => { handleResize(); }); - if (myTableRef.value) { - miniTableResizeObserver.observe(myTableRef.value); + if (miniTableRef.value) { + miniTableResizeObserver.observe(miniTableRef.value); } }); @@ -480,7 +496,7 @@ const tableColumns = computed(() => { col.cellRenderer = renderCellContent; // Header cell renderer - use custom headerCellRenderer if provided - col.headerCellRenderer = undefined; // TODO + col.headerCellRenderer = renderHeaderCellContent; col._listTableColumn = column; return col;