滚动行为
在路由之间导航时,@esmx/router 会自动管理滚动位置以符合用户预期。推送到新页面时滚动到顶部;返回时恢复之前的滚动位置。这与传统多页面网站的行为一致。
默认行为
Router 根据导航类型以不同方式处理滚动:
push:滚动到顶部(0, 0)replace:滚动到顶部(0, 0)back:恢复保存的滚动位置forward:恢复保存的滚动位置go(n):恢复保存的滚动位置pushWindow:由浏览器处理replaceWindow:由浏览器处理
这开箱即用,无需任何配置。
滚动位置的保存方式
离开页面时(通过 push、replace 或历史记录导航),Router 会使用两种机制保存当前滚动位置:
- 内存映射:一个以页面完整 URL 为键的
Map<string, ScrollPosition> - 历史状态:位置也会存储在
history.state的__scroll_position_key属性中
存储在 history.state 中意味着滚动位置在页面刷新后仍然有效——当用户刷新后再导航返回时,仍然可以恢复正确的滚动位置。
手动滚动恢复
Router 会自动设置 history.scrollRestoration = 'manual'。这告诉浏览器不要尝试自行进行滚动恢复,将完全控制权交给 Router。
这是在导航的 confirm 阶段配置的——你无需自行设置。
保持滚动位置
有时你不希望导航滚动到顶部。例如,在切换标签页或筛选内容时,用户希望保持在当前位置:
当 keepScrollPosition 设置为 true 时:
- 页面不会滚动到顶部
- 当前滚动位置不会被保存(因为我们停留在同一位置)
__keepScrollPosition标志会存储在history.state中
在 back/forward 导航期间也会检查此标志——如果目标历史记录条目是使用 keepScrollPosition: true 创建的,则会跳过滚动恢复。
滚动到元素
滚动系统支持使用 CSS 选择器滚动到页面上的特定元素。你可以通过 el 属性指定目标:
- CSS 选择器字符串(例如
'#my-id'、'.my-class'、'[data-section]') - DOM
Element引用
如果你需要在导航后滚动到某个元素,请使用 afterEach 钩子结合原生滚动 API:
层与滚动
通过层路由打开的路由(使用 pushLayer 或 createLayer)会完全跳过滚动处理。由于层在当前页面之上以覆盖层的形式渲染,滚动背景页面会造成干扰:
此行为内置于 Router 的 confirm 阶段——当 router.isLayer 为 true 时,会跳过滚动逻辑。
滚动位置流程
以下是不同导航类型中滚动处理的完整流程:
push / replace
back / forward / go
窗口导航 (pushWindow / replaceWindow)
总结
- push/replace 时滚动到顶部:默认启用。传递
keepScrollPosition: true可禁用。 - back/forward 时恢复滚动:默认启用。自动使用保存的位置。
- 浏览器滚动恢复:已禁用(
'manual')。由 Router 自动设置。 - 层的滚动处理:已跳过。对层自动生效。
- 跨页面刷新持久化:通过
history.state。自动完成。