什么是动态路由?
动态路由是一种路径不固定的路由,路径中可变的部分被称为动态路径参数(Dynamic Segment),使用动态路径参数可以提高路由规则的可复用性。在Vue Router的路由路径中,使用“:参数名”的方式可以在路径中定义动态路径参数。
演示如何定义一个动态路由
{ path: '/sub/:id', component: 组件 },
动态路径参数id为参数名
注意:
不同动态路径参数的动态路由在进行切换时,由于它们都是指向同一组件,所以Vue不会销毁再重新创建这个组件,而是复用这个组件。如果想要在切换时进行一些操作,就需要在组件内部利用watch来监听路由的变化。
演示如何在About组件中监听路由的变化
在About组件中利用watch监听路由的变化。
<script setup>
import { useRoute } from 'vue-router'
import { watch } from 'vue'
const route = useRoute()
watch(() => route.path, path => {
console.log('路由路径', path)
})
</script>
获取动态路径params参数值的2种方式:
使用$route.params获取参数值
使用props获取参数值
假设在Movie组件中有“电影1”“电影2”“电影3”这3个链接,单击它们会跳转到同一个MovieDetails组件,并展示对应的电影id,用于区分不用id对应的详情页的数据。
使用$route.params获取参数值
新建src\components\Movie.vue文件,在该文件中定义3个路由链接和路由视图。
<template>
<div class="movie-container">
<router-link to="/movie/1">电影1</router-link>
<router-link to="/movie/2">电影2</router-link>
<router-link to="/movie/3">电影3</router-link>
<router-view></router-view>
</div>
</template>
<style>
.movie-container {
min-height: 150px;
background-color: #f2f2f2;
}
.movie-container a {
padding: 0 5px;
font-size: 18px;
border: 1px solid #ccc;
border-radius: 5px;
color: #000;
margin: 0 5px;
}
</style>
修改src\App.vue文件,在“关于”路由链接下方补充定义“电影”路由链接。
<router-link to="/movie">电影</router-link>
创建src\components\MovieDetails.vue文件,使用$route.params.id获取参数id的值。
<template>
<p>电影{{ $route.params.id }}页面</p> //获取动态匹配的id参数的值
</template>
修改src\router.js文件,在routes中添加路由匹配规则。
routes: [
{ path: '/', redirect: '/movie'},
// 此处省略了/home和/about的路由代码
{
path: '/movie', component: () => import ('./components/Movie.vue'),
children: [
{ path: ':id', component: () => import ('./components/movieDetails.vue') }
]
}
]
在浏览器中访问http://127.0.0.1:5173/。Movie组件初始页面效果、单击“电影1”链接,跳转到MovieDetails组件的效果,如下图所示。

使用props获取参数值
Vue Router允许在路由匹配规则中开启props传参。
① 修改src\components\MovieDetails.vue文件,使用props接收路由规则中匹配到的参数。
<template>
<p>电影{{ id }}页面</p>
</template>
<script setup>
const props = defineProps({
id: String
})
</script>
② 在src\router.js文件中,为“:id”路径的路由开启props传参。
{
path: ':id',
component: () => import ('./components/movieDetails.vue'),
props: true
}