Vue3路由的props

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>



相关推荐
卸任5 小时前
Vibe coding工具使用心得
前端·ai编程
brien95 小时前
为什么模型标称 1M,Google Antigravity 聊到 256K 却突然失忆?我们给它做了个原生行内监控圆环
前端
修炼的dance6 小时前
录屏关键帧间隔多少合适?六档实测,2秒到10秒小了75.6%
前端
Lank_M6 小时前
关键帧从1秒拉到10秒,录屏小87.3%,摄像头小10.8%
前端
补码缩写6 小时前
用 ffprobe 拆录屏,八成字节在 29 个关键帧上
前端
百思不得小李6 小时前
一个复杂的动态表单是如何实现的
前端·设计模式
陈随易6 小时前
Cmder 停更 17 个月,2.0 支持 Windows Terminal
前端·后端·程序员
清晨Coding6 小时前
删了 Cookie 还能自动登录?Google系网站登录态自动恢复的原理分析
javascript
风骏时光牛马6 小时前
前沿视界
前端
kyriewen6 小时前
我扫了 814 个依赖,97 个还敢要 Node 10
前端·javascript·程序员