Skip to content

滚动行为 | Vue Router

什么是滚动行为?

滚动行为控制着页面导航时的滚动位置。Vue Router 允许你自定义导航后的滚动行为,提供更好的用户体验。

基本配置

启用滚动行为

在创建路由器时配置滚动行为:

javascript
const router = createRouter({
  history: createWebHistory(),
  routes: [...],
  scrollBehavior(to, from, savedPosition) {
    // 滚动行为逻辑
  }
})

滚动行为函数参数

to 和 from

  • 类型: RouteLocationNormalized
  • 说明: 目标路由和来源路由对象

savedPosition

  • 类型: { left: number, top: number } | null
  • 说明: 浏览器前进/后退时保存的滚动位置

常见滚动行为模式

1. 滚动到顶部

javascript
scrollBehavior(to, from, savedPosition) {
  // 总是滚动到页面顶部
  return { top: 0 }
}

2. 保持滚动位置(浏览器行为)

javascript
scrollBehavior(to, from, savedPosition) {
  if (savedPosition) {
    // 浏览器前进/后退时恢复位置
    return savedPosition
  } else {
    // 新导航时滚动到顶部
    return { top: 0 }
  }
}

3. 滚动到指定元素

javascript
scrollBehavior(to, from, savedPosition) {
  if (to.hash) {
    // 滚动到锚点元素
    return {
      el: to.hash,
      behavior: 'smooth' // 平滑滚动
    }
  }
  
  if (savedPosition) {
    return savedPosition
  }
  
  return { top: 0 }
}

高级滚动行为

1. 条件性滚动

javascript
scrollBehavior(to, from, savedPosition) {
  // 特定路由不滚动
  if (to.meta.noScroll) {
    return false
  }
  
  // 从列表页到详情页保持位置
  if (from.path === '/products' && to.path.startsWith('/products/')) {
    return savedPosition
  }
  
  // 其他情况滚动到顶部
  return { top: 0 }
}

2. 延迟滚动

javascript
scrollBehavior(to, from, savedPosition) {
  return new Promise((resolve) => {
    setTimeout(() => {
      if (savedPosition) {
        resolve(savedPosition)
      } else if (to.hash) {
        resolve({ el: to.hash })
      } else {
        resolve({ top: 0 })
      }
    }, 300) // 延迟 300ms
  })
}

3. 平滑滚动配置

javascript
scrollBehavior(to, from, savedPosition) {
  if (to.hash) {
    return {
      el: to.hash,
      behavior: 'smooth',
      top: 20 // 距离元素顶部的偏移量
    }
  }
  
  return {
    top: savedPosition ? savedPosition.top : 0,
    behavior: 'smooth'
  }
}

实际应用场景

场景 1:单页应用文档阅读

javascript
scrollBehavior(to, from, savedPosition) {
  // 文档页面保持阅读位置
  if (to.path.startsWith('/docs/') && from.path.startsWith('/docs/')) {
    return savedPosition
  }
  
  // 锚点导航
  if (to.hash) {
    return {
      el: to.hash,
      behavior: 'smooth',
      top: 80 // 考虑固定头部的高度
    }
  }
  
  return { top: 0 }
}

场景 2:电商网站

javascript
scrollBehavior(to, from, savedPosition) {
  // 商品列表保持滚动位置
  if (from.path === '/products' && to.path === '/products') {
    return savedPosition
  }
  
  // 商品详情页回到顶部
  if (to.path.startsWith('/product/')) {
    return { top: 0 }
  }
  
  // 购物车页面特殊处理
  if (to.path === '/cart') {
    return { top: 0, behavior: 'smooth' }
  }
  
  return savedPosition || { top: 0 }
}

场景 3:管理后台

javascript
scrollBehavior(to, from, savedPosition) {
  // 相同模块内保持位置
  const toModule = to.path.split('/')[1]
  const fromModule = from.path.split('/')[1]
  
  if (toModule === fromModule) {
    return savedPosition
  }
  
  // 切换模块时滚动到顶部
  return { top: 0 }
}

滚动行为最佳实践

1. 考虑固定头部

javascript
scrollBehavior(to, from, savedPosition) {
  if (to.hash) {
    return {
      el: to.hash,
      top: 80, // 固定头部高度
      behavior: 'smooth'
    }
  }
  
  return { top: 0 }
}

2. 性能优化

javascript
scrollBehavior(to, from, savedPosition) {
  // 避免不必要的滚动
  if (to.path === from.path) {
    return
  }
  
  return savedPosition || { top: 0 }
}

3. 可访问性考虑

javascript
scrollBehavior(to, from, savedPosition) {
  // 为屏幕阅读器用户提供更好的体验
  if (to.meta.shouldFocusMain) {
    setTimeout(() => {
      const main = document.querySelector('main')
      if (main) {
        main.focus()
      }
    }, 100)
  }
  
  return savedPosition || { top: 0 }
}

故障排除

常见问题及解决方案

  1. 滚动不生效

    • 检查路由配置是否正确
    • 确认组件已正确挂载
  2. 锚点滚动偏移

    • 考虑固定定位元素的高度
    • 使用 top 属性进行偏移调整
  3. 平滑滚动不兼容

    • 提供回退方案
    • 检测浏览器支持情况

🎯 总结:合理的滚动行为配置可以显著提升用户体验,特别是在内容丰富的单页应用中。通过精心设计的滚动逻辑,可以让导航变得更加流畅和直观。

🚀 Vue Router - 让前端路由变得简单而强大 | 构建现代化单页应用的最佳选择