fix 拖动流畅度

This commit is contained in:
zwgczx committed 2026-02-26 18:04:36 +08:00
1 parent 37f4a99914
commit 57a2029847
13 files changed
+576 -64

No files matched your search

+75 -1
View File
@@ -56,6 +56,7 @@ const dataMenuOpen = ref(false)
const dataMenuRef = ref<HTMLElement | null>(null)
const importFileRef = ref<HTMLInputElement | null>(null)
const tabItemElMap = new Map<string, HTMLElement>()
const tabPanelElMap = new Map<string, HTMLElement>()
const tabsModel = computed({
get: () => tabStore.tabs,
@@ -125,6 +126,14 @@ const setTabItemRef = (id: string, el: Element | ComponentPublicInstance | null)
tabItemElMap.delete(id)
}
const setTabPanelRef = (id: string, el: Element | ComponentPublicInstance | null) => {
if (el instanceof HTMLElement) {
tabPanelElMap.set(id, el)
return
}
tabPanelElMap.delete(id)
}
const ensureActiveTabVisible = () => {
const activeId = tabStore.activeTabId
const el = tabItemElMap.get(activeId)
@@ -132,6 +141,50 @@ const ensureActiveTabVisible = () => {
el.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'nearest' })
}
const getActivePanelScrollViewport = (tabId?: string | null) => {
if (!tabId) return null
const panelEl = tabPanelElMap.get(tabId)
if (!panelEl) return null
return panelEl.querySelector<HTMLElement>('[data-slot="scroll-area-viewport"]')
}
const getTabScrollSessionKey = (tabId: string) => `tab-scroll-top:${tabId}`
const saveTabInnerScrollTop = (tabId?: string | null) => {
if (!tabId) return
const viewport = getActivePanelScrollViewport(tabId)
if (!viewport) return
const top = viewport.scrollTop || 0
try {
sessionStorage.setItem(getTabScrollSessionKey(tabId), String(top))
} catch (error) {
console.error('save tab scroll failed:', error)
}
}
const restoreTabInnerScrollTop = (tabId?: string | null) => {
if (!tabId) return
const viewport = getActivePanelScrollViewport(tabId)
if (!viewport) return
let top = 0
try {
top = Number(sessionStorage.getItem(getTabScrollSessionKey(tabId)) || '0') || 0
} catch (error) {
console.error('restore tab scroll failed:', error)
}
viewport.scrollTop = top
}
const scheduleRestoreTabInnerScrollTop = (tabId?: string | null) => {
if (!tabId) return
requestAnimationFrame(() => {
restoreTabInnerScrollTop(tabId)
requestAnimationFrame(() => {
restoreTabInnerScrollTop(tabId)
})
})
}
const readWebStorage = (storageObj: Storage): DataEntry[] => {
const entries: DataEntry[] = []
for (let i = 0; i < storageObj.length; i++) {
@@ -251,6 +304,7 @@ onMounted(() => {
window.addEventListener('mousedown', handleGlobalMouseDown)
void nextTick(() => {
ensureActiveTabVisible()
scheduleRestoreTabInnerScrollTop(tabStore.activeTabId)
})
})
@@ -260,12 +314,31 @@ onBeforeUnmount(() => {
watch(
() => tabStore.activeTabId,
() => {
(nextId, prevId) => {
saveTabInnerScrollTop(prevId)
void nextTick(() => {
ensureActiveTabVisible()
scheduleRestoreTabInnerScrollTop(nextId)
})
}
)
watch(
() => tabStore.tabs.map(t => t.id),
(ids) => {
const idSet = new Set(ids)
try {
for (let i = sessionStorage.length - 1; i >= 0; i--) {
const key = sessionStorage.key(i)
if (!key || !key.startsWith('tab-scroll-top:')) continue
const tabId = key.slice('tab-scroll-top:'.length)
if (!idSet.has(tabId)) sessionStorage.removeItem(key)
}
} catch (error) {
console.error('cleanup tab scroll cache failed:', error)
}
}
)
</script>
<template>
@@ -372,6 +445,7 @@ watch(
<div
v-for="tab in tabStore.tabs"
:key="tab.id"
:ref="el => setTabPanelRef(tab.id, el)"
v-show="tabStore.activeTabId === tab.id"
class="h-full w-full p-6 animate-in fade-in duration-300"
>