fix(frontend): ページ遷移でスクロール位置が保持されない問題を修正

Fix #11068
This commit is contained in:
syuilo 2023-07-08 15:30:36 +09:00
parent 644023316e
commit 15683370f0
6 changed files with 53 additions and 47 deletions

View file

@ -1,7 +1,7 @@
// NIRAX --- A lightweight router
import { EventEmitter } from 'eventemitter3';
import { Component, shallowRef, ShallowRef } from 'vue';
import { Component, onMounted, shallowRef, ShallowRef } from 'vue';
import { safeURIDecode } from '@/scripts/safe-uri-decode';
type RouteDef = {
@ -267,13 +267,33 @@ export class Router extends EventEmitter<{
});
}
public replace(path: string, key?: string | null, emitEvent = true) {
public replace(path: string, key?: string | null) {
this.navigate(path, key);
if (emitEvent) {
this.emit('replace', {
path,
key: this.currentKey,
});
}
}
}
export function useScrollPositionManager(getScrollContainer: () => HTMLElement, router: Router) {
const scrollPosStore = new Map<string, number>();
onMounted(() => {
const scrollContainer = getScrollContainer();
scrollContainer.addEventListener('scroll', () => {
scrollPosStore.set(router.getCurrentKey(), scrollContainer.scrollTop);
}, { passive: true });
router.addListener('change', ctx => {
const scrollPos = scrollPosStore.get(ctx.key) ?? 0;
scrollContainer.scroll({ top: scrollPos, behavior: 'instant' });
if (scrollPos !== 0) {
window.setTimeout(() => { // 遷移直後はタイミングによってはコンポーネントが復元し切ってない可能性も考えられるため少し時間を空けて再度スクロール
scrollContainer.scroll({ top: scrollPos, behavior: 'instant' });
}, 100);
}
});
router.addListener('same', () => {
scrollContainer.scroll({ top: 0, behavior: 'smooth' });
});
});
}