一、Vue3 Router 传参有哪几种核心方式?
不少刚开始折腾Vue3项目的同学,一碰到页面跳转传参就发懵:到底有多少种传参方式?不同场景选哪种更稳?参数刷新没了咋救?这篇用问答形式,把Vue3 Router传参的关键知识点、实操技巧和避坑点全唠明白,从基础到细节一次吃透~
Vue3 Router 传参方式主要围绕「路由配置」和「跳转时的参数携带」展开,常见的有这四类:
动态路由参数(路径参数)
把参数直接嵌在路由路径里,/user/:id
这种格式,配置路由时用 :参数名
占坑,跳转时把具体值填进去, url 里就会显示成 /user/123
。
params 传参(命名路由的隐式参数)
通过命名路由的 params
字段传参,但只有和动态路由参数匹配的部分才会显式出现在 url;如果路由没配置对应路径参数,这些 params
属于“内存级”参数,刷新页面会丢失。
query 传参(查询参数)
参数跟在 url 的 后面,像 /user?tab=info&page=2
这样,不管路由咋配置,只要跳转时带 query
,参数就会明文出现在 url 里,刷新也不会丢。
props 传参(路由组件解耦方案)
通过路由配置的 props
选项,把路由参数“转成”组件的 props 传入,组件不用直接依赖 useRoute()
,更方便复用和测试。
动态路由参数咋用?适合啥场景?
动态路由参数是“把参数写进 url 路径”的玩法,步骤分两步:配置路由 + 跳转传参 + 接收参数。
配置路由(占坑)
在路由规则里,用 :参数名
定义动态段,
const routes = [ { path: '/user/:id', // id 是动态参数 name: 'User', component: () => import('./views/User.vue') } ]
跳转时传参(填坑)
可以用编程式导航或者声明式导航:
- 编程式(用
router.push
):import { useRouter } from 'vue-router' const router = useRouter() router.push({ name: 'User', params: { id: 123 } }) // 或者直接拼路径:router.push('/user/123')
- 声明式(用
<RouterLink>
):<RouterLink :to="{ name: 'User', params: { id: 123 } }">去用户页</RouterLink> <!-- 或者 <RouterLink to="/user/123">去用户页</RouterLink> -->
组件内接收参数
用 useRoute()
钩子拿参数:
<script setup> import { useRoute } from 'vue-router' const route = useRoute() const userId = route.params.id // 这里的 id 和路由配置里 :id 对应 </script>
适合啥场景?
- 页面唯一性强:比如用户详情、商品详情,每个
id
对应唯一页面, url 里带id
也方便用户收藏/分享。 - SEO 需求:搜索引擎更易抓取带参数的静态路径(
/user/123
比?id=123
更像静态页)。
query 传参和 params 传参有啥区别?
很多同学分不清这俩,核心差异在「参数是否显式在 url」和「刷新是否保留」上,具体看这张对比表:
维度 | query 传参 | params 传参(非动态路由场景) |
---|---|---|
url 显示 | 明文显示在 后(如 ?tab=info ) |
不在 url 显示(仅内存中临时保存) |
刷新保留 | 刷新后参数还在 | 刷新后参数丢失(因为没存在 url 里) |
路由配置依赖 | 不需要路由配置提前占坑 | 若想参数显式在 url,必须配动态路由 |
使用灵活性 | 适合临时筛选、分页等可变参数 | 适合和动态路由绑定的“页面核心标识” |
举个栗子🌰
做电商商品列表,筛选条件(比如价格区间、分类)适合用 query
:因为用户刷新页面后,筛选条件得保留,而且不需要“收藏筛选后的 url”时,用 query
灵活;
做订单详情页,订单 id
是页面核心标识,适合用动态路由参数(属于 params
里和路径绑定的部分),保证 url 里有 id
,刷新也能拿到。
用 props 咋给路由组件传参?
路由组件直接用 `useRoute()` 拿参数,会让组件和路由强耦合(比如复用组件时,得先配路由),用 `props` 传参能解耦,让组件更“纯粹”。
路由配置里开 props: true
当路由是动态路由(如 /user/:id
),把 props
设为 true
,路由的 params
会自动变成组件的 props:
路由配置:
{ path: '/user/:id', name: 'User', component: User, props: true // 关键配置 }
组件里接收:
<script setup> defineProps(['id']) // 直接用 props 接收,不用 useRoute 了 console.log(id) // 能拿到路由里的 :id 参数 </script>
传静态 props(少用,但得知道)
props
设为对象,不管路由参数是啥,组件都拿静态值:
{ path: '/user', component: User, props: { tab: 'info' } // 组件拿到的 tab 固定是 'info' }
函数式 props(动态逻辑传参)
props
可以是函数,根据 route
对象返回动态值,适合复杂场景:
{ path: '/user/:id', component: User, props: (route) => { return { id: route.params.id, defaultTab: 'info' // 额外加静态值 } } }
组件接收:
<script setup> defineProps(['id', 'defaultTab']) </script>
为啥推荐用 props?
- 解耦路由依赖:组件不用关心“我是不是路由组件”,复用的时候直接传 props 就行。
- 测试更简单:写单元测试时,不用模拟路由,直接传 props 就能测。
编程式导航和声明式导航传参有啥不同?
Vue3 里跳转页面分「编程式(用 JS 逻辑跳)」和「声明式(用
编程式导航(router.push / router.replace 等)
适合有逻辑判断后再跳转的场景,比如点击按钮后,先调接口存数据,再跳页面:
import { useRouter } from 'vue-router' const router = useRouter() const handleClick = async () => { await saveData() // 调接口存数据 router.push({ name: 'Success', query: { msg: '保存成功' } }) }
声明式导航(
适合页面上的静态链接,比如导航栏、菜单:
<RouterLink :to="{ name: 'Article', params: { id: 456 }, query: { from: 'home' } }" > 看文章 </RouterLink>
核心区别
- 编程式是逻辑里的动态跳转,能结合异步操作、条件判断;
- 声明式是模板里的静态跳转,更直观,适合用户能直接点的链接。
传参后刷新页面,参数丢了咋解决?
碰到“跳转时参数有值,刷新页面就没了”,十有八九是「params 传参没和动态路由绑定」导致的。
问题根源
如果用 params
传参,但路由没配置对应的动态路径参数,这些 params
只存在内存里,刷新页面时,路由重新初始化,内存里的参数就没了。
比如错误示范:
路由配置是 path: '/user'
(没配 :id
),但跳转时传 params: { id: 123 }
,id
不会出现在 url ,刷新就丢。
解决方法
根据需求选方案:
-
需要参数刷新保留 → 用 query 传参
把参数放到query
里,不管路由咋配,query
会明文存在 url ,刷新不丢:router.push({ name: 'User', query: { id: 123 } }) // url 变成 /user?id=123 ,刷新后 route.query.id 还在
-
参数是页面核心标识 → 用动态路由参数
把参数写到路由路径里(配:id
),这样参数既在 url 里,刷新也能拿到:// 路由配置 { path: '/user/:id', ... } // 跳转 router.push({ name: 'User', params: { id: 123 } }) // url 是 /user/123 ,刷新后 route.params.id 还在
-
临时参数,刷新丢了也没事 → 继续用 params(但得接受刷新丢失)
如果参数是临时用的(比如表单跳转前的临时状态),丢了也不影响,那继续用params
传参就行,不用改。
多参数传递时,怎么组织更清晰?
页面跳转时,经常要传多个参数(id、类型、筛选条件),乱传容易搞混,得按“参数重要性 + 场景”分类传。
分类传参逻辑
- 核心标识参数(如用户 id、商品 id):用动态路由参数,写进 url 路径,保证刷新不丢,且页面唯一性强。
- 可变筛选参数(如分页、tab 切换、搜索关键词):用query 传参,明文在 url ,刷新保留,还能让用户通过 url 分享筛选状态。
- 临时逻辑参数(如是否弹窗、临时标记):用params 传参(非动态路由场景),但要接受刷新丢失。
举个综合栗子🌰
做一个“商品详情 + 评论 tab + 分页”的页面:
- 商品
id
是核心 → 动态路由:path: '/product/:id'
- tab(是看详情还是评论)、分页
page
→ query 传参:query: { tab: 'comment', page: 2 }
- 临时标记(比如是否自动展开评论)→ params 传参(非动态路由,刷新丢了也没事)
跳转代码:
router.push({ name: 'Product', params: { id: 789 }, // 动态路由参数 query: { tab: 'comment', page: 2 }, // 筛选参数 params: { autoOpen: true } // 临时参数(注意:这里如果路由没配 :autoOpen,刷新会丢) })
这样分类后,参数用途清晰,维护起来也方便~
Vue3 组合式 API 里,咋获取路由参数?
Vue3 的 <script setup>
语法里,获取路由参数得用 `useRoute()` 钩子,步骤很简单:
导入并调用 useRoute
<script setup> import { useRoute } from 'vue-router' const route = useRoute() // 拿到当前路由对象 </script>
取 params 或 query
- 取动态路由参数 / params :
route.params.参数名
- 取 query 参数:
route.query.参数名
示例(承接动态路由例子):
<template> <div>用户ID:{{ userId }}</div> <div>当前标签:{{ activeTab }}</div> </template> <script setup> import { useRoute } from 'vue-router' const route = useRoute() const userId = route.params.id // 动态路由参数 const activeTab = route.query.tab // query 参数 </script>
注意点
useRoute()
必须在组合式 API 上下文里用(<script setup>
或 setup()
函数里),不能在普通函数、生命周期钩子外乱用,否则拿不到路由对象~
传参时容易踩的坑,咋避?
最后聊聊踩坑经验,提前避坑少掉头发~
坑1:params 传参没配动态路由,刷新丢参数
→ 解决:核心参数用动态路由或 query;临时参数接受丢失,或者转成 query。
坑2:路由配置了动态参数,但跳转时没传,页面崩了
→ 解决:跳转前做参数校验,或者路由配置里给动态参数设默认(path: '/user/:id?'
加问号表示可选)。
坑3:用了 props: true ,但组件没定义对应 props
→ 解决:组件里用 defineProps
声明接收的参数,defineProps(['id'])
。
坑4:编程式导航用 path 跳转时,传 params 不生效
→ 原因:用 path
跳转时,params
会被忽略(因为 path 是静态字符串,没法绑定 params)。
→ 解决:要么用 name + params
跳转,要么把参数拼到 path 里(如 /user/123
)。
把这些传参方式、场景、避坑点理清楚后,Vue3 页面跳转传参就不再是玄学啦~下次写项目时,先想清楚参数的“重要性”和“是否要刷新保留”,再选对应的传参方式,代码逻辑会清爽很多~如果还有细节没搞懂,评论区随时喊我~
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。