Vue Composition API 中的路由实践指南

一、useRouter 和 useRoute 的使用

在 Vue 3 的 Composition API 中,我们不再通过 this.$routerthis.$route 访问路由实例和当前路由,而是使用 useRouteruseRoute 函数。

基本用法

import { useRouter, useRoute } from 'vue-router'

export default {
  setup() {
    const router = useRouter()
    const route = useRoute()

    // 编程式导航
    const navigateToHome = () => {
      router.push('/home')
    }

    // 访问当前路由参数
    const userId = computed(() => route.params.id)

    return {
      navigateToHome,
      userId
    }
  }
}

主要区别

特性useRouter (router)useRoute (route)
用途控制导航访问当前路由信息
常用方法/属性push, replace, goparams, query, meta
响应式

实践建议

  • 在组件销毁时无需取消订阅,因为 useRoute 返回的是响应式对象
  • 对于频繁访问的路由属性,可以使用 computed 进行缓存
  • 在非组件环境中(如 store),可以通过导入 router 实例直接使用

二、组合式 API 中的导航守卫

全局守卫

// main.js
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'

const app = createApp(App)

router.beforeEach((to, from, next) => {
  // 全局前置守卫逻辑
  next()
})

app.use(router)
app.mount('#app')

组件内守卫

在 Composition API 中,我们可以使用 onBeforeRouteUpdateonBeforeRouteLeave

import { onBeforeRouteLeave, onBeforeRouteUpdate } from 'vue-router'

export default {
  setup() {
    onBeforeRouteUpdate((to, from, next) => {
      // 在当前路由改变但组件被复用时调用
      next()
    })

    onBeforeRouteLeave((to, from, next) => {
      // 导航离开该组件的对应路由时调用
      next()
    })
  }
}

路由独享守卫

const routes = [
  {
    path: '/user/:id',
    component: User,
    beforeEnter: (to, from, next) => {
      // 路由独享守卫
      next()
    }
  }
]

实践建议

  • 对于权限控制等全局逻辑,使用全局守卫
  • 对于特定路由的验证逻辑,使用路由独享守卫
  • 组件内守卫适合处理与组件状态相关的导航控制
  • 在组合式 API 中,守卫可以更灵活地组织在 setup 函数中

三、动态路由与响应式数据结合

动态路由匹配

const routes = [
  {
    path: '/user/:userId',
    component: User,
    props: true // 将 params 作为 props 传递
  }
]

响应式数据绑定

import { useRoute, watch } from 'vue-router'

export default {
  setup() {
    const route = useRoute()
    
    // 当路由参数变化时重新获取数据
    watch(
      () => route.params.userId,
      (newUserId) => {
        fetchUserData(newUserId)
      },
      { immediate: true }
    )
  }
}

动态添加路由

import { useRouter } from 'vue-router'

export default {
  setup() {
    const router = useRouter()
    
    const addDynamicRoute = () => {
      router.addRoute({
        path: '/new-route',
        component: () => import('./NewRoute.vue')
      })
    }
    
    return { addDynamicRoute }
  }
}

实践建议

  • 使用 watch 监听路由变化时,注意添加 immediate: true 以立即执行
  • 对于复杂的数据获取逻辑,考虑使用 watchEffect
  • 动态添加的路由在页面刷新后会丢失,需要配合持久化方案
  • 使用 router.hasRoute() 检查路由是否已存在

四、高级模式:路由与组合式函数

我们可以将路由逻辑封装为可复用的组合式函数:

// useRouteParams.js
import { useRoute, watch } from 'vue-router'
import { ref } from 'vue'

export function useRouteParams(paramName) {
  const route = useRoute()
  const paramValue = ref(route.params[paramName])
  
  watch(
    () => route.params[paramName],
    (newVal) => {
      paramValue.value = newVal
    }
  )
  
  return { paramValue }
}

使用示例:

export default {
  setup() {
    const { paramValue: userId } = useRouteParams('userId')
    
    return { userId }
  }
}

五、常见问题与解决方案

1. 组件复用时的数据刷新

onBeforeRouteUpdate(async (to, from, next) => {
  if (to.params.id !== from.params.id) {
    await fetchData(to.params.id)
  }
  next()
})

2. 导航重复问题

router.push('/path').catch(err => {
  if (err.name !== 'NavigationDuplicated') {
    // 处理其他错误
  }
})

3. 滚动行为控制

const router = createRouter({
  history: createWebHistory(),
  scrollBehavior(to, from, savedPosition) {
    if (savedPosition) {
      return savedPosition
    } else {
      return { top: 0 }
    }
  }
})

总结

Vue 3 的组合式 API 为路由管理带来了更灵活的组织方式。通过 useRouteruseRoute,我们可以在组件中更清晰地访问路由功能。结合响应式系统,可以轻松实现路由参数与组件状态的同步。导航守卫的组合式 API 版本提供了更好的代码组织能力,而动态路由与响应式数据的结合则让复杂路由场景的实现变得更加简单。

在实际项目中,建议:

  1. 将路由相关逻辑封装为组合式函数提高复用性
  2. 合理使用各种导航守卫控制应用流
  3. 注意处理动态路由的持久化和状态管理
  4. 利用 TypeScript 增强路由的类型安全

评论已关闭