滚动行为

当路由切换时,浏览器默认会保持当前的滚动位置。vitarx-router 提供了 scrollBehavior 配置项,让你可以精确控制页面切换时的滚动行为。

scrollBehavior 配置

createRouter 中配置 scrollBehavior 函数:

ts
import { createRouter } from 'vitarx-router'

const router = createRouter({
  routes: [...],
  scrollBehavior(to, from, savedPosition) {
    // 返回滚动目标
    return { top: 0, left: 0, behavior: 'smooth' }
  }
})

函数签名:

ts
type BeforeScrollCallback = (
  to: RouteLocation,
  from: RouteLocation,
  savedPosition: ScrollPosition | null
) => ScrollTarget | false | void

返回值说明

返回值说明
ScrollTarget滚动到指定位置
false禁用路由器内部的滚动处理
void使用默认行为

ScrollTarget 接口

ts
interface ScrollTarget {
  /** 滚动到指定元素(CSS 选择器) */
  el?: string
  /** 水平滚动位置 */
  left?: number
  /** 垂直滚动位置 */
  top?: number
  /** 滚动行为:'auto' | 'instant' | 'smooth' */
  behavior?: ScrollBehavior
}

常见用法

滚动到顶部:

ts
scrollBehavior() {
  return { top: 0, left: 0 }
}

平滑滚动到顶部:

ts
scrollBehavior() {
  return { top: 0, left: 0, behavior: 'smooth' }
}

滚动到指定元素:

ts
scrollBehavior(to) {
  if (to.hash) {
    return { el: to.hash, behavior: 'smooth' }
  }
  return { top: 0 }
}

禁用滚动:

ts
scrollBehavior() {
  return false
}

默认行为

如果没有配置 scrollBehavior,路由器使用以下默认行为:

  1. 如果目标路由包含 hash(如 #section),滚动到对应元素
  2. 否则滚动到页面顶部 { top: 0, left: 0 }

savedPosition

savedPosition 参数在用户使用浏览器的前进/后退按钮时提供之前保存的滚动位置:

ts
scrollBehavior(to, from, savedPosition) {
  // 如果有保存的位置(前进/后退),恢复到之前的位置
  if (savedPosition) {
    return savedPosition
  }
  // 如果有 hash,滚动到对应元素
  if (to.hash) {
    return { el: to.hash }
  }
  // 否则滚动到顶部
  return { top: 0, left: 0 }
}

INFO

savedPosition 仅在使用 router.go()router.back()router.forward() 导航时才有值,编程式导航(push/replace)时为 null

完整示例

ts
import { createRouter } from 'vitarx-router'
import type { RouteLocation, ScrollPosition } from 'vitarx-router'

const router = createRouter({
  routes: [...],
  scrollBehavior(
    to: RouteLocation,
    from: RouteLocation,
    savedPosition: ScrollPosition | null
  ) {
    // 1. 前进/后退时恢复滚动位置
    if (savedPosition) {
      return { ...savedPosition, behavior: 'auto' }
    }

    // 2. 有 hash 时滚动到锚点
    if (to.hash) {
      return { el: to.hash, behavior: 'smooth' }
    }

    // 3. 从列表页进入详情页时保持位置
    if (from.path === '/articles' && to.path.startsWith('/article/')) {
      return false
    }

    // 4. 默认滚动到顶部
    return { top: 0, left: 0, behavior: 'instant' }
  }
})