From: Eduardo San Martin Morote Date: Wed, 15 Apr 2020 14:43:22 +0000 (+0200) Subject: feat(scroll): handle scroll on popstate X-Git-Tag: v4.0.0-alpha.6~15 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=181efe9f29a200b03e2d8f4759e7854047936824;p=thirdparty%2Fvuejs%2Frouter.git feat(scroll): handle scroll on popstate --- diff --git a/src/router.ts b/src/router.ts index aca64d92..2fbc2e66 100644 --- a/src/router.ts +++ b/src/router.ts @@ -18,6 +18,9 @@ import { ScrollToPosition, ScrollPosition, scrollToPosition, + saveScrollOnLeave, + getScrollKey, + getSavedScroll, } from './utils/scroll' import { createRouterMatcher } from './matcher' import { createRouterError, ErrorTypes, NavigationError } from './errors' @@ -420,9 +423,12 @@ export function createRouter({ // TODO: this doesn't work on first load. Moving it to RouterView could allow automatically handling transitions too maybe // TODO: refactor with a state getter const state = isPush || !isClient ? {} : window.history.state - handleScroll(toLocation, from, state && state.scroll).catch(err => - triggerError(err, false) - ) + const savedScroll = getSavedScroll(getScrollKey(toLocation.fullPath, 0)) + handleScroll( + toLocation, + from, + savedScroll || (state && state.scroll) + ).catch(err => triggerError(err, false)) // navigation is confirmed, call afterGuards for (const guard of afterGuards.list()) guard(toLocation, from) @@ -439,6 +445,8 @@ export function createRouter({ pendingLocation = toLocation const from = currentRoute.value + saveScrollOnLeave(getScrollKey(from.fullPath, info.distance)) + try { await navigate(toLocation, from) finalizeNavigation( diff --git a/src/utils/scroll.ts b/src/utils/scroll.ts index 5d57b31c..2a4da686 100644 --- a/src/utils/scroll.ts +++ b/src/utils/scroll.ts @@ -65,3 +65,24 @@ export function scrollToPosition(position: ScrollPosition): void { window.scrollTo(normalizedPosition.x, normalizedPosition.y) } } + +/** + * TODO: refactor the scroll behavior so it can be tree shaken + */ + +export const scrollPositions = new Map() + +export function getScrollKey(path: string, distance: number): string { + const position: number = history.state + ? history.state.position - distance + : -1 + return position + path +} + +export function saveScrollOnLeave(key: string) { + scrollPositions.set(key, computeScrollPosition()) +} + +export function getSavedScroll(key: string) { + return scrollPositions.get(key) +}