Vue.js Router里的query params怎么用?要注意哪些点?
做Vue项目时,路由传参是绕不开的需求,尤其是query params(查询参数),很多刚接触的同学会疑惑:query params咋用?和params有啥不同?传参、取值、处理刷新这些场景咋搞?今天就把Vue Router里query params的关键知识点拆成问题一个个讲清楚,帮你避开踩坑~
query params和params在Vue Router里有啥本质区别?
首先得搞明白这俩不是一回事,从定义、表现、刷新逻辑到路由配置都有区别:
- 定义和表现:query params是URL里
?key=value形式的参数(比如/list?page=2&sort=price),属于“查询”性质;params是路径里的动态片段(比如/user/:id对应/user/123),属于“路径参数”。 - 刷新保留性:query params存在URL里,页面刷新后数据还在;如果params没写在URL里(比如用
params传参但路由没配占位符),刷新就会丢失(因为 params 存在内存里,不是URL的一部分)。 - 路由配置要求:params必须在路由规则里提前写占位符(比如
path: '/user/:id'),否则传了也不生效;query params不用在路由配置里写,想传啥参数随时加,更灵活。
举个例子:要做用户详情页,用户ID是核心路径参数,就用params(配/user/:id);要是做用户列表的筛选(比如按性别、年龄筛),这些临时筛选条件就用query params(路径还是/user-list,加?gender=male&age=20-30)。
怎么在Vue Router的路由规则里配置query params?
先划个重点:query params不需要在路由配置里预先定义!
路由配置主要管“路径结构”和“params参数”,
const routes = [
{
path: '/product', // 路径是/product,没有query相关配置
name: 'Product',
component: Product
}
]
哪怕你跳转时要加?type=electronics&brand=huawei,路由规则里也不用写这些query的key——因为query是“附加”在路径上的查询参数,属于动态可扩展的,不需要提前占坑。
用跳转时,咋传query params?
要是用字符串拼接(比如to="/search?keyword=手机&category=数码"),得自己处理中文、特殊字符的编码,容易踩坑,所以对象语法更安全,Vue Router会自动帮你编码~
编程式导航(this.$router.push)传query params咋写?
编程式导航同样用对象语法,逻辑和
methods: {
goArticle() {
this.$router.push({
path: '/article',
query: {
id: 1001, // 文章ID
tab: 'comment' // 默认显示评论tab
}
})
}
}
跳转后URL是/article?id=1001&tab=comment。
也可以用name代替path(比如name: 'Article'),效果一样,但注意:如果用name+params,params是路径参数;而query是查询参数,和name/path搭配都能传~
页面组件里咋获取query params?
分选项式API(Vue2)和组合式API(Vue3)两种情况:
选项式API(Vue2)
直接通过this.$route.query取参数,比如在mounted里:
export default {
mounted() {
const articleId = this.$route.query.id; // 取id参数
const activeTab = this.$route.query.tab; // 取tab参数
this.fetchArticle(articleId); // 根据ID请求文章数据
}
}
组合式API(Vue3)
需要引入useRoute钩子,然后访问route.query:
import { useRoute } from 'vue-router'
export default {
setup() {
const route = useRoute()
const articleId = route.query.id
const activeTab = route.query.tab
// ...业务逻辑
}
}
注意响应性:$route是响应式对象,当query变化时(比如从/article?id=1001跳到/article?id=1002,路径不变只有query变),组件不会重新创建,这时候要监听query变化,可以用watch或者路由守卫:
// 选项式API用watch
watch: {
'$route.query'(newQuery, oldQuery) {
if (newQuery.id !== oldQuery.id) {
this.fetchArticle(newQuery.id)
}
}
}
// 组合式API用watch
watch(
() => route.query.id,
(newId) => {
fetchArticle(newId)
}
)
页面刷新后,query params还能保留吗?
能!因为query params是URL的一部分,浏览器刷新时会保留URL里的查询参数,Vue Router也会重新解析$route.query。
举个例子:当前URL是/search?keyword=手机&page=2,刷新页面后,this.$route.query.keyword还是'手机',page还是'2'。
但如果是用params传参(且没写在URL里),刷新就会丢数据,所以需要“刷新保留”的参数(比如搜索词、分页),优先用query params~
多个query params咋组织?能传对象或数组吗?
query params支持传对象、数组,但要注意编码和解码逻辑:
传对象
比如想传筛选条件对象{ price: [100, 200], brand: '华为' },可以用JSON.stringify转成字符串:
this.$router.push({
path: '/filter',
query: {
filter: JSON.stringify({ price: [100, 200], brand: '华为' })
}
})
URL会变成/filter?filter=%7B%22price%22%3A%5B100%2C200%5D%2C%22brand%22%3A%22%E5%8D%8E%E4%B8%BA%22%7D(这是URL编码后的结果)。
接收时要解码并解析:
const filterStr = route.query.filter const filterObj = JSON.parse(decodeURIComponent(filterStr))
传数组
直接传数组{ tags: ['vue', 'js'] },Vue Router会把数组转成重复键的形式:
this.$router.push({
path: '/tag',
query: { tags: ['vue', 'js'] }
})
URL变成/tag?tags=vue&tags=js,接收时route.query.tags是数组['vue', 'js']。
但要注意后端接口的兼容性:如果后端要求tags=vue,js这种逗号分隔的形式,得自己处理成字符串再传,别让后端解析数组时翻车~
query params能用来做页面搜索、筛选、分页功能吗?
必须能!这正是query params的核心应用场景:
- 搜索功能:把关键词存在
query里,比如/search?keyword=手机,用户分享链接时,别人打开能直接看到相同搜索结果;刷新页面,关键词也不会丢。 - 筛选功能:比如电商商品页的“价格区间、品牌、销量排序”,把这些条件存在
query(/product?price=100-500&brand=apple&sort=sales),组件根据这些参数发起请求,渲染对应商品。 - 分页功能:列表页的
page=2存在query里,用户跳转到第二页后,刷新或返回还能停在第二页。
举个完整例子:
<template>
<div>
<input v-model="keyword" placeholder="搜索关键词" />
<button @click="handleSearch">搜索</button>
</div>
</template>
<script>
export default {
data() {
return { keyword: '' }
},
methods: {
handleSearch() {
this.$router.push({
path: '/search',
query: { keyword: this.keyword }
})
}
}
}
</script>
搜索页组件在created里取query发起请求:
export default {
created() {
const keyword = this.$route.query.keyword
this.fetchSearchResult(keyword) // 根据关键词请求数据
}
}
路由守卫(导航守卫)里咋处理query params?
路由守卫能在“路由变化前/后”做逻辑,处理query params很常用的场景是监听query变化,更新数据。
组件内守卫(beforeRouteUpdate)
当组件复用(路径不变,只有query变)时,用beforeRouteUpdate监听:
export default {
beforeRouteUpdate(to, from) {
// 如果page参数变化,重新请求列表
if (to.query.page !== from.query.page) {
this.page = to.query.page
this.fetchList()
}
}
}
全局守卫(router.beforeEach)
全局守卫可以统一处理query参数的合法性,比如分页的page必须是数字:
router.beforeEach((to, from, next) => {
const page = to.query.page
if (page && isNaN(Number(page))) {
// page不是数字,重定向到page=1
next({ ...to, query: { ...to.query, page: 1 } })
} else {
next()
}
})
query params的编码和解码需要注意什么?
URL里的特殊字符(比如中文、空格、& 等)必须编码,否则会解析错误,Vue Router会自动帮我们做编码,但接收时要注意解码逻辑:
- 简单参数(如字符串、数字):
$route.query会自动解码,比如传keyword=手机,拿到的this.$route.query.keyword是'手机',不用手动解码。 - 复杂参数(如对象、数组):如果用
JSON.stringify传参,URL里是编码后的字符串,接收时要手动decodeURIComponent再JSON.parse,比如前面讲的传对象的例子。
别手动拼接URL传参!比如写成/search?keyword=手机,中文“手机”没编码的话,URL可能变成/search?keyword=%E6%89%8B%E6%9C%BA(自动编码),但如果是自己拼接特殊字符(比如&),容易导致参数截断,所以优先用对象语法传query,让Vue Router自动处理编码~
错误使用query params容易踩哪些坑?
总结几个高频踩坑点,避坑指南拿走:
-
混淆query和params:
以为params能像query一样“随便传”,结果路由没配/:id这种占位符,导致params传了也不显示在URL里,刷新就丢数据,路径参数用params(需配占位符),查询参数用query(不配占位符)。 -
组件不更新,query变化没反应:
同一个路由页面,只有query变化时,组件不会重新创建,所以要手动监听query变化(用watch或beforeRouteUpdate),否则数据不会更新。 -
特殊字符导致解析错误:
手动拼接URL传参时,没处理中文、&等字符,导致URL解析错误(比如参数被截断),解决方案:用对象语法传query,让Vue Router自动编码。 -
刷新后数据“丢失”?不,是没处理请求逻辑:
query刷新后还在,但如果组件里的请求逻辑只在mounted执行,刷新时mounted会重新执行,所以要确保mounted里读取query并发起请求。 -
多值参数和后端接口不兼容:
传数组导致URL里出现?tags=vue&tags=js,但后端需要tags=vue,js这种格式,这时候要自己把数组转成逗号分隔的字符串再传。
实际项目中,query params的最佳实践有哪些?
最后给几个落地建议,让代码更健壮:
-
关键参数放query:
需要“分享、刷新保留、SEO友好”的参数(如搜索词、分页、筛选条件),优先存在query里;敏感数据(如用户token)别放query,因为URL会暴露。 -
统一用对象语法传参:
和`this.$router.push`都用`{ path: 'xxx', query: { ... } }`形式,避免编码问题。 -
监听query变化,及时更新数据:
用watch或beforeRouteUpdate处理query变化时的逻辑(比如重新请求数据),别让页面数据和URL参数“不同步”。 -
复杂参数序列化:
传对象、数组时,用JSON.stringify转成字符串,接收时JSON.parse+decodeURIComponent,保证数据结构不丢。 -
参数验证+默认值:
在路由守卫或组件内检查query参数(比如页码必须是正整数),不合法就设默认值(如page=1),避免接口报错。 -
配合SEO优化:
对需要SEO的页面(如博客、商品列表),把核心参数放query里(如/article?category=前端&tag=vue),让爬虫能抓取到关键信息。
看完这些问题,是不是对Vue Router的query params清晰多了?其实核心就是理解“query是URL上的查询参数,灵活且刷新保留”,然后掌握传参、取值、处理变化这几个关键步骤,实际项目里多练几遍,踩过坑就记住啦~要是还有其他路由问题,评论区随时喊我~
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
code前端网



发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。