Vue3路由的props
props的作用
它在路由里面的作用很简单,就是是把路由参数、或者自定义数据,直接喂给路由组件当作props使用,上面说的路由参数也就是我们之前使用params或者query传的参数;
props的写法
- 布尔值
只传递params参数,参数名和组件的props一致,写法如:{ path: '/goods/:goodsId', component: GoodsDetail, props: true }
- 对象
传递自定义的静态数据,与路由参数毫无关系,写法如:{ path: '/goods/:goodsId', component: GoodsDetail, props: { isHot: true } }
- 函数
传递params/query参数,转换参数类型,拼接自定义数据,这个一般情况下是最常用的;写法如:{ path: '/goods/:goodsId', component: GoodsDetail, props: (route) => ({ goodsId: Number(route.params.goodsId), source: route.query.source }) }
小案例
比如我们以一个非常简单的校园社团系统作为例子
- 首先我们先看路由配置
vue
//引入vue-router相关函数,创建路由实例,并使用HTML5的history模式
import { createRouter, createWebHistory } from "vue-router";
import ClubDetailBool from "../components/ClubDetailBool.vue";
import ClubDetailFunc from "../components/ClubDetailFunc.vue";
import ClubDetailObj from "../components/ClubDetailObj.vue";
const routes = [{
path: '/club/bool/:clubId',
name: 'ClubDetailBool',
component: ClubDetailBool,
props: true
}]
const router = createRouter({
history: createWebHistory(),
routes
});
export default routes;
- 现在我们先创建一个社团列表的组件
js
<template>
<div class="club-list">
<h2>校园社团列表</h2>
<button @click="goToBool(1)">查看【布尔值写法】篮球社详情</button>
</div>
</template>
<script>
import { useRouter } from 'vue-router';
const router = useRouter();
const goToBool = (clubId) => {
router.push(`/club/bool/${clubId}`);
};
</script>
<style scoped>
button {
margin: 10px;
padding: 8px 16px;
cursor: pointer;
}
</style>
- 我们先说第一个布尔值的案例
js
//ClubDetailBool.vue
<template>
<div class="club-detail">
<h3>社团详情</h3>
<!-- 这个只能拿到params里面的clubID,拿不到静态数据和query参数 -->
<p>社团ID:{{ clubId }}</p>
</div>
</template>
<script setup>
//接受props名称必须和路由参数名称一致
const props = defineProps({
clubId: {
type: String,
required: true
}
});
</script>

- 对象和函数的案例
js
import { createRouter, createWebHistory, RouteLocationNormalized } from 'vue-router'
// 导入三个组件,分别对应三种props写法(实际项目可复用一个组件,这里为了清晰分开)
import ClubDetailBool from '../components/ClubDetailBool.vue'
import ClubDetailObj from '../components/ClubDetailObj.vue'
import ClubDetailFunc from '../components/ClubDetailFunc.vue'
const routes = [
// 写法1:布尔值 ------ 只传递params参数(clubId),参数名和组件props名一致
{
path: '/club/bool/:clubId',
name: 'ClubDetailBool',
component: ClubDetailBool,
props: true // 布尔值写法:自动把params里的clubId传给组件的props
},
// 写法2:对象 ------ 传递静态数据(和路由参数无关)
{
path: '/club/obj/:clubId', // 路径仍带clubId,但对象写法拿不到,仅做演示
name: 'ClubDetailObj',
component: ClubDetailObj,
props: {
recruitStatus: '招新中', // 静态数据:不管路由参数是什么,组件都能拿到这个值
maxMember: 50 // 静态数据:社团最大人数50
}
},
// 写法3:函数(最常用)------ 混合传递params/query/静态数据,还能处理参数类型
{
path: '/club/func/:clubId',
name: 'ClubDetailFunc',
component: ClubDetailFunc,
props: (route: RouteLocationNormalized) => ({
clubId: Number(route.params.clubId), // 把params的clubId(字符串)转数字
source: route.query.source || '首页', // 拿query参数(比如/club/func/1?source=社团列表)
recruitStatus: '招新中', // 静态数据
maxMember: 50 // 静态数据
})
}
]
const router = createRouter({
history: createWebHistory(),
routes
})
export default router
- 创建对象案例的组件
vue
//ClubDetailObj.vue
<template>
<div class="club-detail">
<h3>【对象写法】社团详情</h3>
<p>招新状态:{{ recruitStatus }}</p>
<p>最大人数:{{ maxMember }}</p>
<p>备注:只能拿到静态数据,拿不到clubId/query参数</p>
</div>
</template>
<script setup>
// 接收props:名称和路由props对象里的键一致
const props = defineProps({
recruitStatus: String,
maxMember: Number
})
</script>
- 父组件
js
<template>
<div class="club-list">
<h2>校园社团列表</h2>
<!-- 跳转布尔值写法的详情页 -->
<button @click="goToBool(1)">查看【布尔值写法】篮球社详情</button>
<!-- 跳转对象写法的详情页 -->
<button @click="goToObj(1)">查看【对象写法】篮球社详情</button>
<!-- 跳转函数写法的详情页(带query参数) -->
<button @click="goToFunc(1)">查看【函数写法】篮球社详情</button>
</div>
</template>
<script setup>
import { useRouter } from 'vue-router'
const router = useRouter()
// 跳转布尔值写法
const goToBool = (clubId) => {
router.push({
name: 'ClubDetailBool',
params: { clubId }
})
}
// 跳转对象写法
const goToObj = (clubId) => {
router.push({
name: 'ClubDetailObj',
params: { clubId } // 虽然传了clubId,但对象写法拿不到
})
}
// 跳转函数写法(带query参数)
const goToFunc = (clubId) => {
router.push({
name: 'ClubDetailFunc',
params: { clubId },
query: { source: '社团列表' }
})
}
</script>
<style scoped>
button {
margin: 10px;
padding: 8px 16px;
cursor: pointer;
}
</style>
- App.vue也需要样式,让其好看一点
js
<template>
<!-- 页面整体布局 -->
<div id="app">
<!-- 导航栏:快速切换不同路由(三种 props 写法) -->
<nav class="nav">
<h2>Vue3 路由 props 三种写法演示</h2>
<div class="nav-buttons">
<!-- 跳转布尔值写法路由 -->
<router-link to="/club/bool/1" class="nav-link" active-class="active">
布尔值写法(仅传 params)
</router-link>
<!-- 跳转对象写法路由 -->
<router-link to="/club/obj/1" class="nav-link" active-class="active">
对象写法(仅传静态数据)
</router-link>
<!-- 跳转函数写法路由(带 query 参数) -->
<router-link to="/club/func/1?source=导航栏" class="nav-link" active-class="active">
函数写法(混合传参+类型处理)
</router-link>
<!-- 回到社团列表页 -->
<router-link to="/" class="nav-link" active-class="active">
社团列表(跳转测试)
</router-link>
</div>
</nav>
<!-- 路由出口:所有路由组件都会渲染到这里 -->
<main class="content">
<router-view />
</main>
</div>
</template>
<script setup>
// App.vue 作为根组件,这里无需额外逻辑,只需要提供路由出口即可
// 若需要全局样式/全局逻辑,可在这里写
</script>
<style scoped>
/* 全局样式(scoped 仅作用于 App.vue,也可抽离到全局样式文件) */
#app {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
font-family: Arial, Helvetica, sans-serif;
}
/* 导航栏样式 */
.nav {
padding: 20px;
background-color: #f5f5f5;
border-radius: 8px;
margin-bottom: 20px;
}
.nav h2 {
margin: 0 0 15px 0;
color: #333;
}
.nav-buttons {
display: flex;
gap: 10px;
flex-wrap: wrap;
}
/* 路由链接样式 */
.nav-link {
padding: 8px 16px;
text-decoration: none;
color: #42b983;
/* Vue 主题色 */
border: 1px solid #42b983;
border-radius: 4px;
transition: all 0.2s;
}
.nav-link:hover {
background-color: #42b983;
color: white;
}
/* 激活的路由链接样式 */
.nav-link.active {
background-color: #42b983;
color: white;
font-weight: bold;
}
/* 内容区域样式 */
.content {
padding: 20px;
border: 1px solid #eee;
border-radius: 8px;
}
</style>


