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前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。