一、先搞懂router params是干啥的?
不少刚学Vue3路由的同学,碰到router params总是犯懵:到底咋传参?页面咋接收?动态路由和params啥关系?刷新后参数没了咋整?今天就把Vue3里router params的用法、坑点、和query的区别这些事儿,掰开了揉碎了讲明白,从基础到进阶一次搞透~
router params是Vue Router里用来在不同页面间传递**“资源标识类数据”**的工具,打个比方,做用户详情页时,每个用户对应唯一ID(比如123),访问路径写成`/user/123`,这里的`123`就是params里的`id`,它的核心作用是**让路由和数据强绑定**——看到路径就知道页面要展示哪个用户、哪件商品的信息。和URL里的“查询参数(query)”比起来,params更像路径里的“动态片段”,比如筛选商品用/goods?category=book&page=2
,category
和page
是query(属于“可选筛选条件”);而用户ID、订单号这类“没它页面就失去意义”的数据,就得用params+动态路由来传。
给router params传参,两种方式要分清
Vue3里传params主要靠声明式导航(
声明式导航:里传params
用to
的对象语法时,必须配合路由的name
(不能用path!),举个实际例子:假设路由配置长这样——
const routes = [ { name: 'User', // 路由的name,传参必须用它 path: '/user/:id', // 动态段:id,对应params里的id component: User } ]
页面里用
<router-link :to="{ name: 'User', // 匹配路由的name params: { id: 123 } // 要传的参数 }" >去用户123的详情页</router-link>
要是写成path: '/user/:id'
再传params,Vue Router会直接忽略params(因为path和params的绑定关系不明确),所以记住:声明式传params,name是关键。
编程式导航:router.push里传params
在setup语法糖里,得先用useRouter
拿到router实例,再用push
方法,代码示例:
<script setup> import { useRouter } from 'vue-router' const router = useRouter() const goToUser = () => { router.push({ name: 'User', // 同样必须用name params: { id: 456 } }) } </script>
和声明式同理,要是写成path: '/user/:id'
再传params,params会被直接忽略,路径里的:id
也不会被替换,等于白传。
页面接收router params,一行代码搞定
传完参后,目标页面(比如User组件)得把params拿出来用,Vue3里用useRoute
钩子,直接取route.params
里的参数就行。
代码示例:
<script setup> import { useRoute } from 'vue-router' const route = useRoute() // 假设路由是/user/:id,这里就能拿到id const userId = route.params.id console.log('当前用户ID:', userId) // 比如打印出123 </script>
如果路由配置里有多个动态段(比如path: '/order/:orderId/:tab'
),那route.params
里就有orderId
和tab
两个属性,按需取值即可。
动态路由匹配:params生效的前提
很多同学传了params但刷新就没了,或者路径不对,核心原因是路由配置没做“动态路由匹配”。
路由配置必须写“动态段”
比如要传用户id,路由得写成path: '/user/:id'
,这里的:id
动态段”,它和params里的id
一一对应,要是路由写成path: '/user'
,然后传params: { id: 123 }
,虽然能跳转,但params只存在于“内存路由记录”里——一旦刷新页面,params就没了(因为URL里没存这个参数)。
所以规则是:想要params刷新不丢,路由必须配置动态段,让参数“嵌”在URL路径里。
多参数的动态路由
如果有多个参数(比如订单页需要订单id和标签),路由可以这么配:
{ path: '/order/:orderId/:tab', name: 'Order', component: Order }
传参时,params里对应写orderId
和tab
;接收时,用route.params.orderId
、route.params.tab
就能拿到值。
params和query传参,区别大到要注意场景
很多同学分不清params和query,导致场景用错,这里从路径表现、刷新保留、使用场景三个维度对比:
对比项 | params(动态路由下) | query |
---|---|---|
路径表现 | 在URL路径里,如/user/123 |
在URL后带,如/goods?page=2 |
刷新后是否保留 | 保留(因为URL里有) | 保留(因为URL里有) |
场景适合 | 资源唯一标识(如用户ID、订单号) | 筛选、分页、可选条件(如搜索关键词) |
举个场景例子:做电商商品列表,“分类”“页码”适合用query(用户分享链接,别人打开能看到同样的筛选结果);而商品详情页的“商品ID”必须用params+动态路由(每个商品对应唯一路径,如/goods/1001
,刷新也得保留ID)。
要是用反了,比如把商品ID放query里,路径变成/goods?productId=1001
,虽然功能能实现,但路径不够“语义化”,也不符合RESTful设计(资源路径应该包含标识)。
params传参不生效?这几个坑要避开
传参时遇到“参数传了但接收不到”“刷新后参数没了”,大概率是踩了这些坑:
用path传params(最常见!)
前面强调过,传params时必须用name
,不能用path
,比如写成这样:
router.push({ path: '/user/:id', // 错误!path里的:id不会被params替换 params: { id: 123 } })
这时候Vue Router会直接忽略params,路径还是/user/:id
(没被替换成123),自然接收不到参数。解决方法:把path改成name。
路由配置没动态段
如果路由是path: '/user'
,然后传params: { id: 123 }
,虽然能跳转,但params只存在于内存中,刷新页面后就没了。解决方法:给路由加动态段,如path: '/user/:id'
。
参数名和动态段不匹配
路由配置是path: '/user/:userId'
,但传参时写params: { id: 123 }
,这时候route.params
里没有userId
,自然拿不到值。解决方法:传参的key和路由动态段的名字保持一致。
进阶:动态路由下的组件更新问题
当用户从/user/1
跳转到/user/2
时,因为是同一个User组件,Vue不会销毁重建组件,所以组件里的生命周期(如onMounted
)不会重新执行,这时候如果依赖params更新数据,就会出问题(比如页面还是用户1的信息)。
用watch监听route.params
在setup里,用watch
监听route.params
的变化:
<script setup> import { useRoute, watch } from 'vue-router' const route = useRoute() watch( () => route.params.id, (newId, oldId) => { // newId是新的用户ID,这里发请求重新获取数据 fetchUserInfo(newId) } ) </script>
用onBeforeRouteUpdate钩子
这是Vue Router提供的导航守卫,在路由更新前触发(同一个组件实例下):
<script setup> import { onBeforeRouteUpdate } from 'vue-router' onBeforeRouteUpdate((to, from) => { // to是目标路由,to.params.id是新ID const newId = to.params.id fetchUserInfo(newId) }) </script>
两种方法选其一就行,目的是在params变化时,强制更新页面数据。
掌握这几步,router params不再难
- 传参:声明式用
<router-link :to="{name, params}">
,编程式用router.push({name, params})
,必须用name
; - 接收:用
useRoute().params.xxx
拿参数; - 路由配置:要传的参数必须在
path
里写动态段(如:id
),否则刷新丢参数; - 场景区分:资源标识用
params+动态路由
,筛选条件用query
; - 踩坑点:别用
path
传params、参数名和动态段要一致、动态路由下要处理组件更新。
把这些逻辑理顺,不管是做用户系统、订单系统还是商品详情页,用router params传参都能游刃有余~要是还有细节没搞懂,评论区随时问,咱们再唠~
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。