Browse Source

WIP: optimize resize performance

dev
hechang27-sprt 3 months ago
parent
commit
9eb47f7b09
  1. 50
      packages/base/data/list-table-v2.vue

50
packages/base/data/list-table-v2.vue

@ -123,6 +123,10 @@ const estimatedHeaderHeight = ref<number | undefined>(undefined);
let miniTableResizeObserver: ResizeObserver | null = null; let miniTableResizeObserver: ResizeObserver | null = null;
let lastMiniTableHeight = 0; let lastMiniTableHeight = 0;
// Track if table is visible in viewport - only probe when visible
const isInViewport = ref(false);
let viewportObserver: IntersectionObserver | null = null;
// Header height constant // Header height constant
type TimestampValue = type TimestampValue =
@ -285,9 +289,10 @@ function estimateTableRowHeight() {
// Observe miniTableRef instead of myTableRef - only re-probe if mini-table's rendered height changes // 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 // This avoids unnecessary re-probing during window resize when container width changes but row heights stay same
onMounted(() => { onMounted(() => {
// Resize handler - only re-probe if the mini-table's actual height changed // Resize handler - only re-probe if the mini-table's actual height changed AND table is visible
const handleResize = lodash.debounce(async () => { const handleResize = lodash.debounce(async () => {
if (!shouldUseProbeRow.value || miniTableData.value.length === 0) { // Skip if not using probe, no data, or not visible in viewport
if (!shouldUseProbeRow.value || miniTableData.value.length === 0 || !isInViewport.value) {
return; return;
} }
@ -315,16 +320,43 @@ onMounted(() => {
estimatedRowHeight.value = newRow; estimatedRowHeight.value = newRow;
estimatedHeaderHeight.value = newHeader; estimatedHeaderHeight.value = newHeader;
}); });
}, 200); }, 50);
// Observe miniTableRef for height changes // ResizeObserver for mini-table 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(() => { miniTableResizeObserver = new ResizeObserver(() => {
handleResize(); handleResize();
}); });
if (miniTableRef.value) { // IntersectionObserver to track viewport visibility
// Only attach ResizeObserver when table is visible, detach when off-screen
// This saves CPU for tables scrolled out of view
viewportObserver = new IntersectionObserver(
(entries) => {
const entry = entries[0];
isInViewport.value = entry.isIntersecting;
if (entry.isIntersecting) {
// Table became visible - reconnect ResizeObserver
if (miniTableRef.value && miniTableResizeObserver) {
miniTableResizeObserver.observe(miniTableRef.value);
}
} else {
// Table went off-screen - disconnect ResizeObserver to save CPU
// Heights are cached, so no need to keep observing
if (miniTableResizeObserver) {
miniTableResizeObserver.disconnect();
}
}
},
{ threshold: 0 } // Trigger as soon as any part is visible
);
if (myTableRef.value) {
viewportObserver.observe(myTableRef.value);
}
// Initial observation of mini-table if already in viewport
if (miniTableRef.value && isInViewport.value && miniTableResizeObserver) {
miniTableResizeObserver.observe(miniTableRef.value); miniTableResizeObserver.observe(miniTableRef.value);
} }
}); });
@ -335,6 +367,10 @@ onUnmounted(() => {
miniTableResizeObserver.disconnect(); miniTableResizeObserver.disconnect();
miniTableResizeObserver = null; miniTableResizeObserver = null;
} }
if (viewportObserver) {
viewportObserver.disconnect();
viewportObserver = null;
}
}); });
const containerStyle = computed(() => { const containerStyle = computed(() => {

Loading…
Cancel
Save