fix 拖动流畅度
This commit is contained in:
1 parent
37f4a99914
commit
57a2029847
13 files changed
+576
-64
No files matched your search
+75
-1
@@ -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"
|
||||
>
|
||||
|
||||
Reference in new issue
Block a user