@@ -20,7 +20,12 @@ import type {
2020 RouteLocationAsString ,
2121 RouteRecordNameGeneric ,
2222} from './typed-routes'
23- import { RouterHistory , HistoryState , NavigationType } from './history/common'
23+ import {
24+ RouterHistory ,
25+ HistoryState ,
26+ NavigationType ,
27+ NavigationInformation ,
28+ } from './history/common'
2429import {
2530 ScrollPosition ,
2631 getSavedScrollPosition ,
@@ -108,7 +113,8 @@ export interface RouterScrollBehavior {
108113 (
109114 to : RouteLocationNormalized ,
110115 from : RouteLocationNormalizedLoaded ,
111- savedPosition : _ScrollPositionNormalized | null
116+ savedPosition : _ScrollPositionNormalized | null ,
117+ info ?: NavigationInformation
112118 ) : Awaitable < ScrollPosition | false | void >
113119}
114120
@@ -203,6 +209,14 @@ export interface RouterOptions extends PathParserOptions {
203209 * @default undefined
204210 */
205211 focusManagement ?: boolean | string
212+ /**
213+ * Enable automatic scroll restoration when navigating the history.
214+ *
215+ * Enabling this option, will register a custom `scrollBehavior` if none is provided.
216+ *
217+ * `focusManagement` and this option are just used to enable some sort of "polyfills" for browsers that do not support the Navigation API.
218+ */
219+ enableScrollManagement ?: true
206220}
207221
208222/**
@@ -1066,6 +1080,7 @@ export function createRouter(
10661080 return
10671081 }
10681082
1083+ toLocation . meta . __info = info
10691084 pendingLocation = toLocation
10701085 const from = currentRoute . value
10711086
@@ -1238,6 +1253,23 @@ export function createRouter(
12381253 return err
12391254 }
12401255
1256+ const { enableScrollManagement, scrollBehavior } = options
1257+
1258+ const useScrollBehavior : RouterScrollBehavior | undefined =
1259+ scrollBehavior ??
1260+ ( enableScrollManagement
1261+ ? async ( to , from , savedPosition , info ) => {
1262+ await nextTick ( )
1263+ if ( info ?. type === 'pop' && savedPosition ) {
1264+ return scrollToPosition ( savedPosition )
1265+ }
1266+ if ( to . hash ) {
1267+ return scrollToPosition ( { el : to . hash , behavior : 'smooth' } )
1268+ }
1269+ return scrollToPosition ( { top : 0 , left : 0 } )
1270+ }
1271+ : undefined )
1272+
12411273 // Scroll behavior
12421274 function handleScroll (
12431275 to : RouteLocationNormalizedLoaded ,
@@ -1246,8 +1278,9 @@ export function createRouter(
12461278 isFirstNavigation : boolean
12471279 ) : // the return is not meant to be used
12481280 Promise < unknown > {
1249- const { scrollBehavior } = options
1250- if ( ! isBrowser || ! scrollBehavior ) return Promise . resolve ( )
1281+ const info = to . meta . __info as NavigationInformation | undefined
1282+ delete to . meta . __info
1283+ if ( ! isBrowser || ! useScrollBehavior ) return Promise . resolve ( )
12511284
12521285 const scrollPosition : _ScrollPositionNormalized | null =
12531286 ( ! isPush && getSavedScrollPosition ( getScrollKey ( to . fullPath , 0 ) ) ) ||
@@ -1257,7 +1290,7 @@ export function createRouter(
12571290 null
12581291
12591292 return nextTick ( )
1260- . then ( ( ) => scrollBehavior ( to , from , scrollPosition ) )
1293+ . then ( ( ) => useScrollBehavior ( to , from , scrollPosition , info ) )
12611294 . then ( position => position && scrollToPosition ( position ) )
12621295 . catch ( err => triggerError ( err , to , from ) )
12631296 }
0 commit comments