mirror of
https://github.com/truewhile/MeBox.git
synced 2026-09-28 03:06:38 +08:00
bug处理
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { shouldRememberScroll } from './useScrollMemory.ts'
|
||||
import { shouldPersistScrollSample, shouldRememberScroll } from './useScrollMemory.ts'
|
||||
|
||||
function check(name: string, condition: boolean) {
|
||||
if (!condition) throw new Error(`useScrollMemory: ${name}`)
|
||||
@@ -11,4 +11,41 @@ check('media detail remembers scroll', shouldRememberScroll('/media/media-1'))
|
||||
check('settings does not remember scroll', !shouldRememberScroll('/settings'))
|
||||
check('player does not remember scroll', !shouldRememberScroll('/play/media-1'))
|
||||
|
||||
check(
|
||||
'route transition collapse is ignored',
|
||||
!shouldPersistScrollSample({
|
||||
current: 0,
|
||||
lastSaved: 1800,
|
||||
height: 400,
|
||||
lastHeight: 4200,
|
||||
}),
|
||||
)
|
||||
check(
|
||||
'intentional scroll to top is persisted',
|
||||
shouldPersistScrollSample({
|
||||
current: 0,
|
||||
lastSaved: 1800,
|
||||
height: 4200,
|
||||
lastHeight: 4200,
|
||||
}),
|
||||
)
|
||||
check(
|
||||
'normal downward scroll is persisted',
|
||||
shouldPersistScrollSample({
|
||||
current: 1900,
|
||||
lastSaved: 1800,
|
||||
height: 4200,
|
||||
lastHeight: 4200,
|
||||
}),
|
||||
)
|
||||
check(
|
||||
'content growth still allows persist',
|
||||
shouldPersistScrollSample({
|
||||
current: 1800,
|
||||
lastSaved: 1800,
|
||||
height: 5200,
|
||||
lastHeight: 4200,
|
||||
}),
|
||||
)
|
||||
|
||||
console.log('useScrollMemory.test.ts ok')
|
||||
|
||||
@@ -39,6 +39,23 @@ export function shouldRememberScroll(pathname: string): boolean {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 路由切换时 Outlet 内容变矮,浏览器会把共享滚动容器的 scrollTop 钳低,
|
||||
* 并可能同步触发 scroll 事件。这种“假滚动”不能写入存储,否则返回时永远回到顶部。
|
||||
*/
|
||||
export function shouldPersistScrollSample(input: {
|
||||
current: number
|
||||
lastSaved: number
|
||||
height: number
|
||||
lastHeight: number
|
||||
}): boolean {
|
||||
const { current, lastSaved, height, lastHeight } = input
|
||||
if (height + 1 < lastHeight && current < lastSaved) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* 记住列表页的滚动位置。页面内容会异步长高,因此恢复期间会监听内容高度,
|
||||
* 直到目标位置可达;期间用户主动滚动会立即接管,避免和恢复逻辑抢滚动条。
|
||||
@@ -61,6 +78,7 @@ export function useScrollMemory(pathname: string, userKey = 'anonymous'): void {
|
||||
let restoreFrame = 0
|
||||
let restorePumpUntil = 0
|
||||
let lastSaved = saved
|
||||
let lastHeight = el.scrollHeight
|
||||
|
||||
const stopRestore = () => {
|
||||
if (restoreFrame) {
|
||||
@@ -80,6 +98,7 @@ export function useScrollMemory(pathname: string, userKey = 'anonymous'): void {
|
||||
restoring = false
|
||||
stopRestore()
|
||||
lastSaved = Math.round(el.scrollTop)
|
||||
lastHeight = el.scrollHeight
|
||||
writeScrollPosition(key, lastSaved)
|
||||
}
|
||||
|
||||
@@ -108,6 +127,19 @@ export function useScrollMemory(pathname: string, userKey = 'anonymous'): void {
|
||||
const saveNow = () => {
|
||||
if (restoring) return
|
||||
const current = Math.round(el.scrollTop)
|
||||
const height = el.scrollHeight
|
||||
if (
|
||||
!shouldPersistScrollSample({
|
||||
current,
|
||||
lastSaved,
|
||||
height,
|
||||
lastHeight,
|
||||
})
|
||||
) {
|
||||
lastHeight = height
|
||||
return
|
||||
}
|
||||
lastHeight = height
|
||||
if (current === lastSaved) return
|
||||
lastSaved = current
|
||||
writeScrollPosition(key, current)
|
||||
@@ -118,6 +150,7 @@ export function useScrollMemory(pathname: string, userKey = 'anonymous'): void {
|
||||
restoring = false
|
||||
stopRestore()
|
||||
lastSaved = Math.round(el.scrollTop)
|
||||
lastHeight = el.scrollHeight
|
||||
writeScrollPosition(key, lastSaved)
|
||||
}
|
||||
|
||||
@@ -172,6 +205,8 @@ export function useScrollMemory(pathname: string, userKey = 'anonymous'): void {
|
||||
window.removeEventListener('touchstart', cancelRestore, true)
|
||||
window.removeEventListener('keydown', onKeyDown, true)
|
||||
stopRestore()
|
||||
// 清理时写入最后一次有效位置,避免依赖已被钳制的 el.scrollTop。
|
||||
writeScrollPosition(key, lastSaved)
|
||||
}
|
||||
}, [pathname, userKey])
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user