chore: create page-transition composable

This commit is contained in:
userquin 2023-02-11 16:20:12 +01:00
parent 6dde98eb78
commit a64c0f4e9b
3 changed files with 51 additions and 29 deletions

View file

@ -14,27 +14,25 @@ defineSlots<{
default: {} default: {}
}>() }>()
const nuxtApp = useNuxtApp()
const router = useRouter() const router = useRouter()
const allowScrollTop = ref(false) const allowScrollTop = ref(false)
const restoreClickHook = () => { usePageTransition({
if (isHydrated.value) { beforeEach: () => {
allowScrollTop.value = false
},
afterHydrated: () => {
if (typeof props.to === 'string') if (typeof props.to === 'string')
allowScrollTop.value = router.currentRoute.value.fullPath === props.to allowScrollTop.value = router.currentRoute.value.fullPath === props.to
else else
allowScrollTop.value = router.currentRoute.value.name === props.to.name allowScrollTop.value = router.currentRoute.value.name === props.to.name
} },
} onTransitionError: () => {
router.afterEach(() => {
allowScrollTop.value = false allowScrollTop.value = false
},
}) })
nuxtApp.hooks.hook('app:suspense:resolve', restoreClickHook)
nuxtApp.hooks.hook('page:finish', restoreClickHook)
useCommand({ useCommand({
scope: 'Navigation', scope: 'Navigation',

View file

@ -0,0 +1,29 @@
export const usePageTransition = (options: {
beforeEach?: typeof noop
afterHydrated?: typeof noop
onTransitionError?: typeof noop
}) => {
const nuxtApp = useNuxtApp()
const router = useRouter()
if (options.beforeEach) {
router.beforeEach(() => {
options.beforeEach?.()
})
}
if (options.onTransitionError) {
router.onError(() => {
options.onTransitionError?.()
})
}
if (options.afterHydrated) {
const nuxtHook = () => {
if (isHydrated.value)
options.afterHydrated?.()
}
nuxtApp.hooks.hook('app:suspense:resolve', nuxtHook)
nuxtApp.hooks.hook('page:finish', nuxtHook)
}
}

View file

@ -1,18 +1,10 @@
export default defineNuxtPlugin((nuxtApp) => { export default defineNuxtPlugin(() => {
const router = useRouter()
const route = useRoute() const route = useRoute()
const track = ref(false) const track = ref(false)
const { y } = useWindowScroll() const { y } = useWindowScroll()
const storage = useLocalStorage<Record<string, number>>('elk-track-scroll', {}) const storage = useLocalStorage<Record<string, number>>('elk-track-scroll', {})
const customRoutes = new Set<string>() const customRoutes = new Set<string>()
router.beforeEach(async () => {
track.value = false
})
router.onError(async () => {
track.value = true
})
const forceScrollToTop = () => { const forceScrollToTop = () => {
storage.value[route.fullPath] = 0 storage.value[route.fullPath] = 0
window.scrollTo({ top: 0, left: 0, behavior: 'smooth' }) window.scrollTo({ top: 0, left: 0, behavior: 'smooth' })
@ -60,18 +52,21 @@ export default defineNuxtPlugin((nuxtApp) => {
const restoreScroll = () => restoreScrollCallback(false) const restoreScroll = () => restoreScrollCallback(false)
const restoreScrollHook = () => { const restoreCustomPageScroll = () => restoreScrollCallback(true)
if (isHydrated.value) {
usePageTransition({
beforeEach: () => {
track.value = false
},
afterHydrated: () => {
restoreScroll().then(() => { restoreScroll().then(() => {
track.value = true track.value = true
}).catch(noop) }).catch(noop)
} },
} onTransitionError: () => {
track.value = true
const restoreCustomPageScroll = () => restoreScrollCallback(true) },
})
nuxtApp.hooks.hook('app:suspense:resolve', restoreScrollHook)
nuxtApp.hooks.hook('page:finish', restoreScrollHook)
watch([track, y, () => route], ([trackEnabled, scrollPosition, r]) => { watch([track, y, () => route], ([trackEnabled, scrollPosition, r]) => {
if (trackEnabled && (!r.meta || !r.meta?.noScrollTrack)) if (trackEnabled && (!r.meta || !r.meta?.noScrollTrack))