Vue Router里的query props该怎么用?要注意啥?
不少做前端开发的同学在玩Vue项目时,碰到Vue Router的query和props结合使用,总会犯嘀咕——这俩咋配合能让组件传参更顺?query props到底能解决啥问题?今儿咱就掰开揉碎了聊聊Vue Router里query props的那些事儿,从基础用法到实际场景,再到避坑技巧,一次讲明白。
query和props在Vue Router里分别是干啥的?
先把基础概念理清楚。query 是路由中 URL 里 后面跟着的参数,/page?name=张三&age=18 里,name 和 age query 参数,它属于路由信息($route)的一部分,作用更像“附加筛选条件”或者“页面状态标记”。
而 props 是 Vue 组件接收外部数据的核心方式,父组件通过 props 把数据传给子组件,子组件用 props 选项声明后就能用,这种方式让组件依赖更清晰,也方便测试(不用关心父组件咋来的,传数据就行)。
Vue Router 里搞了个“骚操作”:能把路由的 query 参数直接映射成组件的 props,这么做的好处是 让组件和路由解耦 —— 组件不用直接去读 this.$route.query,改成用 props 接收,后续换路由逻辑或者测试组件时,直接传模拟数据就行,灵活度拉满!
怎么把query参数转成组件props?
这得在路由配置里动刀子,Vue Router 给 props 配置提供了三种玩法:布尔值、对象、函数,咱重点看和 query 结合的场景:
布尔值模式(简单映射)
如果路由配置里写 props: true,Vue Router 会自动把 route.query 里的所有参数,一股脑传给组件当 props,举个栗子:
// 路由配置
{
path: '/search',
component: SearchComponent,
props: true
}
// 组件里声明props
export default {
props: ['keyword', 'page'], // query里的keyword、page会被传进来
mounted() {
console.log(this.keyword, this.page); // 直接用props,不用碰$route
}
}
这种方式适合 query 参数少、不需要额外处理的场景,但灵活性弱(没法改参数名、加默认值)。
函数模式(自定义处理)
要是想对 query 参数做“加工”(比如改名字、加默认值、转类型),用函数模式更爽,路由配置里的 props 可以是个函数,接收 route 对象当参数,返回要传给组件的 props 对象。
// 路由配置
{
path: '/goods',
component: GoodsList,
props: (route) => {
return {
// query里的page是字符串,转成数字
currentPage: Number(route.query.page) || 1,
// 给分类加默认值,没传就显示“全部”
category: route.query.category || '全部'
};
}
}
// 组件里声明props
export default {
props: {
currentPage: {
type: Number,
required: true
},
category: {
type: String,
default: '全部'
}
},
created() {
this.fetchGoods(this.currentPage, this.category); // 用props发请求
}
}
这种方式能灵活处理 query 参数,比如类型转换、默认值、参数重命名,组件里的 props 也能更“干净”(不用兼容路由里的参数名)。
用query props有啥好处?
很多同学会疑惑:直接用 this.$route.query 也能拿参数,为啥非得绕个 props?这就得聊聊解耦、可维护、可测试这几个关键点了:
组件和路由解耦,测试更简单
如果组件里直接用 this.$route.query,测试时得模拟整个路由对象,特麻烦,但用 props 接收的话,测试组件时直接传假数据就行,比如测试 GoodsList 组件,不用管路由,直接传 { currentPage: 2, category: '手机' } 就能测,清爽!
参数处理集中化,组件更纯粹
路由配置里把 query 转 props 的逻辑(比如类型转换、默认值)集中处理,组件只负责“渲染/逻辑”,不用关心参数从哪来、咋处理的,相当于把“路由层”和“组件层”的职责分开,代码维护起来更顺。
符合单向数据流,Bug 好排查
Vue 里 props 是“父传子”的单向数据流,路由作为“父”把 query 处理后传给组件,组件里 props 变化能清晰追踪,要是直接用 $route,参数变化时组件可能没感知,容易埋 Bug;用 props 的话,配合 watch 或者组件更新机制,能更及时响应变化。
实际开发中哪些场景适合用query props?
别光讲理论,咱结合真实场景唠唠,你就知道这玩意儿多实用了:
列表页带筛选/分页参数
比如电商平台的商品列表,用户选了“价格区间”“分类”“排序方式”,这些筛选条件存在 URL 的 query 里(刷新页面能保留状态),用 query props 把这些参数传给列表组件,组件拿到参数后请求对应数据。
路由配置大概长这样:
{
path: '/products',
component: ProductList,
props: (route) => ({
priceRange: route.query.priceRange || '0-∞',
category: route.query.category || 'all',
sort: route.query.sort || 'new',
page: Number(route.query.page) || 1
})
}
组件里用这些 props 发请求,用户刷新页面,筛选条件还在,体验拉满。
多 Tab 切换保存状态
页面里有多个 Tab(待付款”“待发货”“已完成”),把当前激活的 Tab 标识(activeTab=waitPay)存在 query 里,用 query props 传给 Tab 组件,切换 Tab 时改 URL query,刷新页面 Tab 状态不丢。
举个简单实现:
// 路由配置
{
path: '/order',
component: OrderPage,
props: (route) => ({
activeTab: route.query.activeTab || 'waitPay'
})
}
// 组件里,点击Tab时修改query
import { useRouter } from 'vue-router';
export default {
props: ['activeTab'],
setup(props) {
const router = useRouter();
const changeTab = (tab) => {
router.push({ query: { activeTab: tab } }); // 改query,触发props更新
};
return { changeTab, props };
}
}
搜索页传关键词
搜索页面的关键词一般存在 query 里(/search?keyword=Vue),用 query props 把 keyword 传给搜索组件,组件拿到关键词直接请求搜索接口,就算用户分享 URL,别人打开也能直接看到对应搜索结果,SEO 和体验都照顾到了。
配置query props时容易踩的坑有哪些?
前端开发哪有不踩坑的?提前避坑才能少掉头发,这些常见问题得注意:
参数类型不匹配,组件报错
query 里的参数默认都是字符串!比如你想传 page: 2,但 route.query.page 拿到的是 '2',如果组件 props 声明的是 Number 类型,直接赋值会报错(字符串转数字失败)。
解决办法:在路由的 props 函数里手动转类型。
props: (route) => ({
page: Number(route.query.page) || 1 // 转成数字,没传就给默认值1
})
默认值没处理,props 变成 undefined
query 里没传某个参数,route.query.xxx 会是 undefined,要是组件 props 没给默认值,直接用的时候就会报错(props.xxx.length 会崩)。
解决办法:在路由 props 函数里给默认值,或者组件 props 里声明 default,推荐在路由层处理,因为路由更清楚“这个参数不传时该用啥默认值”。
同路由组件复用,props 不更新
Vue Router 有个机制:如果路由路径不变,只是 query 变了,组件会被复用(不会销毁重建),这时候 props 默认不会自动更新,组件里可能还拿着旧数据。
解决办法有两种:
- 用
watch监听 props 变化,watch(() => props.page, (newVal) => { /* 发请求 */ }); - 给组件加
key,用 query 参数当 key,强制组件重建:<component :key="$route.fullPath" />(但性能略差,谨慎用)。
和params比,query props在传参上有啥不同?
很多同学分不清 query 和 params,这里简单对比下:
| 维度 | query 参数 | params 参数 |
|---|---|---|
| 存储位置 | URL 中 后面(如 /page?name=xx) |
URL 路径里(如 /user/:id → /user/123) |
| 刷新保留 | 刷新页面,参数还在 | 刷新页面,参数也在(只要路由配置对) |
| 传参场景 | 筛选条件、页面状态(非核心标识) | 资源唯一标识(如用户ID、商品ID) |
| props 映射 | 靠 props: true 或函数映射 query |
也能 props: true 映射 params(路由配置要写 /:id) |
简单说,params 更像“资源的身份证”,query 更像“资源的筛选器”,比如做用户详情页,用 params(/user/123);做用户列表筛选,用 query(/users?gender=male&page=1)。
怎么给query props加验证?
组件的 props 本身支持类型验证、必填验证、自定义验证,这步不能省!不然传错参数很难查,举个规范的例子:
export default {
props: {
// 分页页码,必须是数字且大于0
page: {
type: Number,
required: true,
validator: (value) => {
return value > 0;
}
},
// 分类,可选,默认值在路由层处理过,这里兜底
category: {
type: String,
default: 'all'
}
}
}
这样配置后,要是路由传参不符合要求(page 传了 0 或者字符串),Vue 会在控制台报错,帮你快速定位问题。
在组合式API(Composition API)里咋用query props?
用 <script setup> 或者 setup() 语法时,接收 props 更简单了,用 defineProps 就行:
<template>
<div>当前页码:{{ currentPage }}</div>
</template>
<script setup>
import { defineProps } from 'vue';
// 声明props
const props = defineProps(['currentPage', 'category']);
// 直接用props.currentPage
console.log(props.currentPage);
</script>
路由配置和之前一样,用 props 函数处理 query 传给组件,要是想在 setup 里监听 props 变化,用 watch:
<script setup>
import { defineProps, watch } from 'vue';
const props = defineProps(['currentPage']);
watch(
() => props.currentPage,
(newPage) => {
console.log('页码变了,发请求:', newPage);
},
{ immediate: true } // 初始化时执行一次
);
</script>
总结一下
Vue Router 的 query props 本质是把路由的查询参数,通过组件 props 传递,让组件和路由解耦,从配置方式(布尔值、函数)到实际场景(列表筛选、Tab 状态、搜索关键词),再到避坑技巧(类型转换、默认值、组件复用),掌握这些点后,写路由传参的代码会更规范、更好维护。
记住核心逻辑:路由负责处理 URL 里的 query,组件负责用 props 接收干净的数据,把这层关系理清楚,不管是现在的项目迭代,还是以后换路由方案,组件都能稳如老狗~
要是你还有其他关于 Vue Router 或者前端的问题,评论区喊我,咱接着唠!
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
code前端网



