fix: 左右两栏共用滚动容器,滚动位移保持一致
- 将 Layout body (#page-scroll) 作为唯一滚动容器,左右两栏同容器滚动 - 滚动区域从搜索框下方开始,搜索框固定 - 内容区 overflow visible、侧栏 height auto;返回顶部/路由归零改用 page-scroll - 验证:滚动 300px 后两侧 top 均为 -152,搜索框不动,返回顶部有效
This commit is contained in:
+41
-40
@@ -80,7 +80,7 @@ function useRoute() {
|
||||
if (window.location.pathname === path) return
|
||||
window.history.pushState({}, '', path)
|
||||
setRoute(parseRoute(path))
|
||||
document.getElementById('content-scroll')?.scrollTo({ top: 0 })
|
||||
document.getElementById('page-scroll')?.scrollTo({ top: 0 })
|
||||
window.scrollTo({ top: 0 })
|
||||
}
|
||||
|
||||
@@ -191,50 +191,51 @@ export default function AppNext() {
|
||||
return () => source.close()
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
const sync = () => {
|
||||
const inner = document.getElementById('content-scroll')?.scrollTop ?? 0
|
||||
setScrolled(Math.max(inner, window.scrollY) > 4)
|
||||
}
|
||||
sync()
|
||||
window.addEventListener('scroll', sync, { passive: true })
|
||||
document.addEventListener('scroll', sync, { passive: true, capture: true })
|
||||
return () => {
|
||||
window.removeEventListener('scroll', sync)
|
||||
document.removeEventListener('scroll', sync, { capture: true })
|
||||
}
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
const content = document.getElementById('content-scroll')
|
||||
const sider = document.querySelector('aside')
|
||||
if (!(content instanceof HTMLElement) || !(sider instanceof HTMLElement)) return
|
||||
|
||||
// 左右两栏共用一个滚动位置:侧栏没有独立滚动条,滚轮也驱动内容区
|
||||
sider.id = 'sidebar-scroll'
|
||||
sider.style.overflow = 'hidden'
|
||||
let frame = 0
|
||||
const sync = () => {
|
||||
if (frame !== 0) return
|
||||
frame = window.requestAnimationFrame(() => {
|
||||
frame = 0
|
||||
sider.scrollTop = content.scrollTop
|
||||
})
|
||||
}
|
||||
const onWheel = (event: WheelEvent) => {
|
||||
event.preventDefault()
|
||||
content.scrollTop += event.deltaY
|
||||
const main = content?.parentElement
|
||||
const body = main?.parentElement
|
||||
if (
|
||||
!(content instanceof HTMLElement) ||
|
||||
!(main instanceof HTMLElement) ||
|
||||
!(body instanceof HTMLElement)
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
content.addEventListener('scroll', sync, { passive: true })
|
||||
sider.addEventListener('wheel', onWheel, { passive: false })
|
||||
// 左右两栏放进同一个滚动容器:滚动区域从搜索框下方开始,两栏位移完全一致
|
||||
const sider = body.querySelector('aside')
|
||||
body.id = 'page-scroll'
|
||||
body.style.overflowY = 'auto'
|
||||
body.style.overflowX = 'hidden'
|
||||
body.style.marginTop = '88px'
|
||||
body.style.height = 'calc(100% - 88px)'
|
||||
content.style.overflow = 'visible'
|
||||
content.style.marginTop = '0'
|
||||
main.style.height = 'auto'
|
||||
if (sider instanceof HTMLElement) {
|
||||
sider.style.overflow = 'visible'
|
||||
sider.style.height = 'auto'
|
||||
}
|
||||
|
||||
const onScroll = () => setScrolled(body.scrollTop > 4)
|
||||
body.addEventListener('scroll', onScroll, { passive: true })
|
||||
onScroll()
|
||||
|
||||
return () => {
|
||||
content.removeEventListener('scroll', sync)
|
||||
sider.removeEventListener('wheel', onWheel)
|
||||
if (frame !== 0) window.cancelAnimationFrame(frame)
|
||||
sider.id = ''
|
||||
sider.style.overflow = ''
|
||||
body.removeEventListener('scroll', onScroll)
|
||||
body.id = ''
|
||||
body.style.overflowY = ''
|
||||
body.style.overflowX = ''
|
||||
body.style.marginTop = ''
|
||||
body.style.height = ''
|
||||
content.style.overflow = ''
|
||||
content.style.marginTop = ''
|
||||
main.style.height = ''
|
||||
if (sider instanceof HTMLElement) {
|
||||
sider.style.overflow = ''
|
||||
sider.style.height = ''
|
||||
}
|
||||
}
|
||||
}, [])
|
||||
|
||||
@@ -650,7 +651,7 @@ export default function AppNext() {
|
||||
</div>
|
||||
</Layout>
|
||||
|
||||
<BackToTop visible={scrolled} />
|
||||
<BackToTop visible={scrolled} targetId="page-scroll" />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user