第7章:路由管理

第19节:路由配置进阶

7.19.1 动态路由与参数

动态路由是指在路由路径中包含动态参数,用于匹配不同的URL但使用相同的组件。

基本用法

const routes = [
  // 静态路由
  { path: '/users', component: UsersList },
  // 动态路由,:id是动态参数
  { path: '/users/:id', component: UserDetail }
]

访问路由参数

在组件中可以通过$route.paramsuseRoute().params访问路由参数:

<!-- UserDetail.vue -->
<template>
  <div>
    <h3>用户详情</h3>
    <p>用户ID: {{ $route.params.id }}</p>
  </div>
</template>

<!-- 使用组合式API -->
<script setup>
import { useRoute } from 'vue-router'

const route = useRoute()
console.log(route.params.id) // 访问路由参数
</script>

路由参数的类型

可以在路由路径中定义多个参数:

const routes = [
  // 多个参数
  { path: '/users/:id/posts/:postId', component: UserPost },
  // 可选参数(Vue Router 4.x支持)
  { path: '/users/:id/:name?', component: UserDetail },
  // 正则表达式参数
  { path: '/users/:id(\\d+)', component: UserDetail } // 只匹配数字ID
]

路由参数变化的处理

当路由参数发生变化时,组件不会重新创建,而是复用现有组件。可以通过以下方式处理参数变化:

  1. 使用watch监听参数变化
<script setup>
import { useRoute, watch } from 'vue-router'

const route = useRoute()

watch(
  () => route.params.id,
  (newId, oldId) => {
    // 参数变化时执行的逻辑
    console.log(`ID从${oldId}变为${newId}`)
    // 重新获取数据
    fetchUserData(newId)
  }
)
</script>
  1. 使用beforeRouteUpdate导航守卫
// 选项式API
export default {
  beforeRouteUpdate(to, from, next) {
    // 参数变化时执行的逻辑
    this.id = to.params.id
    this.fetchData()
    next()
  }
}

将参数作为props传递

可以通过props选项将路由参数作为props传递给组件,使组件更加解耦:

const routes = [
  // 布尔模式:将所有参数作为props传递
  { path: '/users/:id', component: UserDetail, props: true },
  
  // 对象模式:传递固定的props
  { path: '/users/:id', component: UserDetail, props: { admin: false } },
  
  // 函数模式:自定义props
  { 
    path: '/users/:id', 
    component: UserDetail, 
    props: (route) => ({
      id: route.params.id,
      query: route.query,
      admin: route.query.admin === 'true'
    })
  }
]

在组件中使用props接收:

<script setup>
// 使用props接收路由参数
const props = defineProps(['id', 'admin'])

console.log(props.id) // 路由参数
console.log(props.admin) // 传递的props
</script>

7.19.2 嵌套路由配置

嵌套路由允许在父路由组件中嵌套子路由组件,实现复杂的页面结构。

基本用法

const routes = [
  {
    path: '/users',
    component: UsersLayout,
    // 嵌套路由
    children: [
      // 匹配 /users
      { path: '', component: UsersList },
      // 匹配 /users/:id
      { path: ':id', component: UserDetail },
      // 匹配 /users/:id/posts
      { path: ':id/posts', component: UserPosts }
    ]
  }
]

父组件中需要包含&lt;router-view&gt;来显示子路由组件:

<!-- UsersLayout.vue -->
<template>
  <div class="users-layout">
    <h2>用户管理</h2>
    <nav>
      <router-link to="/users">用户列表</router-link>
    </nav>
    
    <!-- 子路由视图 -->
    <div class="users-content">
      <router-view />
    </div>
  </div>
</template>

嵌套路由的参数传递

嵌套路由可以继承父路由的参数:

const routes = [
  {
    path: '/users/:id',
    component: UserLayout,
    children: [
      // 匹配 /users/:id
      { path: '', component: UserDetail },
      // 匹配 /users/:id/posts/:postId
      { path: 'posts/:postId', component: UserPost }
    ]
  }
]

在子路由组件中可以访问父路由的参数:

<script setup>
import { useRoute } from 'vue-router'

const route = useRoute()
console.log(route.params.id) // 父路由参数
console.log(route.params.postId) // 子路由参数
</script>

7.19.3 命名路由与命名视图

命名路由

命名路由允许通过名称引用路由,而不是通过路径,使路由更加灵活:

const routes = [
  {
    path: '/users/:id',
    name: 'user-detail', // 命名路由
    component: UserDetail
  }
]

使用命名路由进行导航:

<!-- 模板中使用 -->
<router-link :to="{ name: 'user-detail', params: { id: 1 } }">用户详情</router-link>

<!-- 组件中使用 -->
<script setup>
import { useRouter } from 'vue-router'

const router = useRouter()
router.push({ name: 'user-detail', params: { id: 1 } })
</script>

命名视图

命名视图允许在同一级路由中显示多个组件:

const routes = [
  {
    path: '/',
    // 命名视图
    components: {
      default: Home,
      sidebar: Sidebar,
      header: Header
    }
  },
  {
    path: '/about',
    components: {
      default: About,
      sidebar: AboutSidebar,
      header: AboutHeader
    }
  }
]

在模板中使用命名视图:

<template>
  <div id="app">
    <!-- 命名视图:header -->
    <router-view name="header" />
    
    <div class="main-content">
      <!-- 命名视图:sidebar -->
      <router-view name="sidebar" />
      <!-- 默认视图 -->
      <router-view />
    </div>
  </div>
</template>

7.19.4 重定向与别名

重定向

重定向用于将一个路由重定向到另一个路由:

const routes = [
  // 基本重定向
  { path: '/home', redirect: '/' },
  
  // 使用命名路由重定向
  { path: '/home', redirect: { name: 'home' } },
  
  // 动态重定向
  { 
    path: '/users/:id', 
    redirect: (to) => {
      // 根据参数动态重定向
      return { path: `/profile/${to.params.id}` }
    }
  }
]

别名

别名允许为路由定义多个路径,访问不同的路径会显示相同的组件:

const routes = [
  // 别名:访问 /home 或 / 都会显示 Home 组件
  { path: '/', component: Home, alias: '/home' },
  
  // 多个别名
  { path: '/users', component: Users, alias: ['/people', '/members'] }
]

总结

在本节中,我们学习了Vue Router的进阶配置,包括:

  1. 动态路由与参数:学习了如何定义动态路由,如何访问路由参数,以及如何将参数作为props传递给组件
  2. 嵌套路由配置:学习了如何创建嵌套路由,实现复杂的页面结构,以及如何处理嵌套路由的参数传递
  3. 命名路由与命名视图:学习了如何使用命名路由进行导航,以及如何使用命名视图在同一级路由中显示多个组件
  4. 重定向与别名:学习了如何使用重定向将一个路由重定向到另一个路由,以及如何使用别名定义多个路径访问同一个组件

这些进阶配置使Vue Router更加灵活和强大,可以满足各种复杂的路由需求。通过学习和掌握这些高级功能,你可以构建更加复杂和完整的单页面应用。

在下一节中,我们将学习Vue Router的编程式导航与路由守卫,进一步提高路由的控制能力。

« 上一篇 Vue Router基础 下一篇 » 19-programmatic-navigation-guards