페이지 렌더 후 스크롤 적용
This commit is contained in:
@@ -2,12 +2,16 @@
|
||||
* 공개 라우트 이동 후 새 화면 기준으로 스크롤 위치를 정리한다.
|
||||
*
|
||||
* Vue Router 기본 scrollBehavior는 전환 중 이전 화면을 먼저 움직일 수 있어
|
||||
* `app/router.options.js`에서 끄고, 여기서는 라우트가 확정된 뒤 프레임을
|
||||
* 기다렸다가 새 화면에서만 최상단 또는 해시 위치로 이동한다.
|
||||
* `app/router.options.js`에서 끄고, 여기서는 Nuxt 페이지 렌더링이 끝난 뒤
|
||||
* 새 화면에서만 최상단 또는 해시 위치로 이동한다.
|
||||
*/
|
||||
export default defineNuxtPlugin((nuxtApp) => {
|
||||
const router = nuxtApp.$router
|
||||
|
||||
/** @type {{ id: number, to: import('vue-router').RouteLocationNormalizedLoaded, from: import('vue-router').RouteLocationNormalizedLoaded } | null} */
|
||||
let pendingRouteScroll = null
|
||||
let routeScrollId = 0
|
||||
|
||||
/**
|
||||
* 브라우저 렌더 프레임을 기다린다.
|
||||
* @returns {Promise<void>} 프레임 대기 Promise
|
||||
@@ -19,18 +23,45 @@ export default defineNuxtPlugin((nuxtApp) => {
|
||||
})
|
||||
|
||||
/**
|
||||
* 이동 완료 후 스크롤 위치를 적용한다.
|
||||
* 이동 완료 후 적용할 스크롤 정보를 저장한다.
|
||||
* @param {import('vue-router').RouteLocationNormalizedLoaded} to - 이동 대상 라우트
|
||||
* @param {import('vue-router').RouteLocationNormalizedLoaded} from - 이전 라우트
|
||||
* @returns {Promise<void>}
|
||||
* @returns {void}
|
||||
*/
|
||||
const applyRouteScroll = async (to, from) => {
|
||||
const queueRouteScroll = (to, from) => {
|
||||
if (to.fullPath === from.fullPath) {
|
||||
return
|
||||
}
|
||||
|
||||
routeScrollId += 1
|
||||
pendingRouteScroll = {
|
||||
id: routeScrollId,
|
||||
to,
|
||||
from
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 새 페이지 렌더링 이후 스크롤 위치를 적용한다.
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
const applyPendingRouteScroll = async () => {
|
||||
const routeScroll = pendingRouteScroll
|
||||
|
||||
if (!routeScroll) {
|
||||
return
|
||||
}
|
||||
|
||||
await waitForFrame()
|
||||
|
||||
if (!pendingRouteScroll || pendingRouteScroll.id !== routeScroll.id) {
|
||||
return
|
||||
}
|
||||
|
||||
pendingRouteScroll = null
|
||||
|
||||
const { to } = routeScroll
|
||||
|
||||
if (to.hash) {
|
||||
const targetId = decodeURIComponent(to.hash.slice(1))
|
||||
const target = document.getElementById(targetId)
|
||||
@@ -49,6 +80,8 @@ export default defineNuxtPlugin((nuxtApp) => {
|
||||
}
|
||||
|
||||
router.afterEach((to, from) => {
|
||||
applyRouteScroll(to, from)
|
||||
queueRouteScroll(to, from)
|
||||
})
|
||||
|
||||
nuxtApp.hook('page:finish', applyPendingRouteScroll)
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user