]> git.ipfire.org Git - thirdparty/vuejs/router.git/commitdiff
feat(scroll): handle scroll on popstate
authorEduardo San Martin Morote <posva13@gmail.com>
Wed, 15 Apr 2020 14:43:22 +0000 (16:43 +0200)
committerEduardo San Martin Morote <posva13@gmail.com>
Wed, 15 Apr 2020 14:43:22 +0000 (16:43 +0200)
src/router.ts
src/utils/scroll.ts

index aca64d920c1de473a2bd7fae663711ccc4faa239..2fbc2e66fea5aa3e9db942c7dab0ce0a56a77a4d 100644 (file)
@@ -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(
index 5d57b31ca9d365b96034be65ca0670a52112f23a..2a4da68602ff03e1447957a1fa6c73493df62012 100644 (file)
@@ -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<string, ScrollToPosition>()
+
+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)
+}