1. 初识useRoute与useRouter路由管理的左右手刚接触Vue3的组合式API时很多人会对useRoute和useRouter这对双胞胎产生困惑。我在重构后台管理系统时就踩过坑——有次在用户详情页想同时显示用户ID和实现返回按钮功能结果把两个API混用导致路由守卫失效。这让我意识到它们就像汽车的仪表盘和方向盘一个负责显示状态当前路由信息一个负责控制方向路由跳转。在用户登录后跳转的场景中典型用法是这样的// 登录成功后跳转 const router useRouter() router.push(/dashboard) // 在仪表盘组件中获取用户ID const route useRoute() const userId route.params.iduseRoute返回的对象包含这些常用属性path当前路径如/user/123params动态参数如{id: 123}query查询字符串如?namefoohashURL哈希值如#sectionname命名路由名称matched匹配的路由记录数组2. 深度对比静态读取vs动态操作2.1 useRoute的静态特性剖析上周我遇到个典型场景在电商后台需要根据URL中的商品ID展示详情。这时useRoute就是最佳选择const route useRoute() const productId ref() onMounted(() { productId.value route.params.id fetchProductDetail(productId.value) })但要注意三个坑直接解构会失去响应性const { params } useRoute()是错误的参数变化需要手动监听watch( () route.params.id, (newId) { fetchProductDetail(newId) } )hash变化不会触发组件重载需要单独监听route.hash2.2 useRouter的动态能力解密在用户权限控制中useRouter的这些方法最常用push跳转到新路由会记录历史replace替换当前路由无历史记录go前进/后退指定步数back等同于浏览器后退forward等同于浏览器前进实战中我推荐这样封装路由跳转const router useRouter() const safeNavigate (path) { // 添加权限校验等逻辑 if(hasPermission(path)) { router.push(path) } else { router.push(/403) } }3. 组合使用实战用户登录跳转案例3.1 登录成功后的跳转处理完整登录流程应该这样实现// 在登录组件中 const router useRouter() const login async () { try { await authService.login(credentials) // 携带token跳转到首页 router.push({ path: /dashboard, query: { t: new Date().getTime() } // 避免缓存 }) } catch (err) { // 异常处理 } }3.2 目标页面的数据加载在仪表盘页面中const route useRoute() const loading ref(true) onMounted(() { loadData() }) watch( () route.query.t, () { // 当时间戳变化时刷新数据 loadData() } ) const loadData () { loading.value true api.getDashboardData() .finally(() { loading.value false }) }4. 高级技巧与性能优化4.1 路由守卫的巧妙组合在管理后台中我这样实现权限控制// 在路由配置中 const routes [ { path: /admin, component: AdminLayout, beforeEnter: (to, from) { const router useRouter() if (!store.state.user.isAdmin) { router.replace(/login?redirect to.path) return false } } } ]4.2 路由元信息的高级用法定义路由时添加meta信息const routes [ { path: /settings, meta: { requiresAuth: true, transition: fade } } ]在组件中获取const route useRoute() console.log(route.meta.transition) // 输出fade4.3 性能优化实践路由懒加载const router createRouter({ routes: [ { path: /big-data, component: () import(./BigData.vue) } ] })持久化路由状态// 保存滚动位置 router.afterEach((to, from) { if (from.meta.saveScroll) { from.meta.scrollY window.scrollY } }) router.beforeEach((to) { if (to.meta.saveScroll to.meta.scrollY) { nextTick(() { window.scrollTo(0, to.meta.scrollY) }) } })5. 常见问题排查指南5.1 路由更新但组件不刷新解决方案// 方案1监听路由变化 watch( () route.params.id, (newVal) { // 重新获取数据 } ) // 方案2给router-view添加key router-view :key$route.fullPath /5.2 路由循环跳转问题在权限控制中经常遇到的坑// 错误示例会导致无限循环 router.beforeEach((to) { if (!isLogin to.path ! /login) { router.push(/login) } }) // 正确写法 router.beforeEach((to) { if (!isLogin to.path ! /login) { return /login // 使用return而不是router.push } })5.3 动态路由的缓存策略对于商品详情页这类动态路由// 在路由配置中 { path: /product/:id, component: ProductDetail, props: true // 将params自动作为props传递 } // 在组件中 defineProps([id]) // 直接接收id参数