From 8b499b6096b52d52ab60f8718154d7fa61cd66c7 Mon Sep 17 00:00:00 2001 From: Eduardo San Martin Morote Date: Thu, 30 Jan 2020 18:22:15 +0100 Subject: [PATCH] feat(history): save scroll on leave/reload --- src/history/html5.ts | 20 +++++++++++++++----- src/router.ts | 9 ++++++++- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/src/history/html5.ts b/src/history/html5.ts index 8d98b167..acffcf26 100644 --- a/src/history/html5.ts +++ b/src/history/html5.ts @@ -120,14 +120,28 @@ function useHistoryListeners( return teardown } + function beforeUnloadListener() { + const { history } = window + if (!history.state) return + history.replaceState( + { + ...history.state, + scroll: computeScrollPosition(), + }, + '' + ) + } + function destroy() { for (const teardown of teardowns) teardown() teardowns = [] window.removeEventListener('popstate', popStateHandler) + window.removeEventListener('beforeunload', beforeUnloadListener) } - // settup the listener and prepare teardown callbacks + // settup the listeners and prepare teardown callbacks window.addEventListener('popstate', popStateHandler) + window.addEventListener('beforeunload', beforeUnloadListener) return { pauseListeners, @@ -259,10 +273,6 @@ function useHistoryStateNavigation(base: string) { } export default function createHistory(base: string = ''): RouterHistory { - if ('scrollRestoration' in window.history) { - history.scrollRestoration = 'manual' - } - const historyNavigation = useHistoryStateNavigation(base) const historyListeners = useHistoryListeners( base, diff --git a/src/router.ts b/src/router.ts index 5a030b10..72c35214 100644 --- a/src/router.ts +++ b/src/router.ts @@ -71,6 +71,8 @@ export interface Router { isReady(): Promise } +const isClient = typeof window !== 'undefined' + export function createRouter({ history, routes, @@ -91,6 +93,10 @@ export function createRouter({ let errorHandlers: ErrorHandler[] = [] let ready: boolean = false + if (isClient && 'scrollRestoration' in window.history) { + window.history.scrollRestoration = 'manual' + } + function resolve( to: RouteLocation, currentLocation?: RouteLocationNormalized /*, append?: boolean */ @@ -160,7 +166,7 @@ export function createRouter({ ) } - // TODO: should we allow partial redirects? I think we should because it's impredictable if + // TODO: should we allow partial redirects? I think we should not because it's impredictable if // there was a redirect before // if (!('path' in newLocation) && !('name' in newLocation)) throw new Error('TODO: redirect canot be relative') @@ -277,6 +283,7 @@ export function createRouter({ const from = currentRoute.value currentRoute.value = markNonReactive(toLocation) + // TODO: this doesn't work on first load. Moving it to RouterView could allow automatically handling transitions too maybe if (!isFirstNavigation) handleScroll(toLocation, from).catch(err => triggerError(err, false)) -- 2.47.3