Vue2 router query 怎么用?常见问题全解答
很多做前端开发的小伙伴,在学Vue2路由的时候,对query参数这块经常犯迷糊——怎么传参?怎么接收?刷新后数据还在吗?和params有啥区别?今天就把Vue2 router query的常见问题掰碎了讲清楚,从基础用法到实战场景,帮你彻底搞懂~
Vue2里router query是干啥的?
先理解路由参数的两种形式:路径参数(params)和查询参数(query),query就像浏览器地址栏里后面跟着的键值对,比如百度搜索“前端学习”后,url里的wd=前端学习
就是查询参数。
在Vue2路由中,query的核心作用是在不同页面间传递“不需要隐藏”的参数,这些参数会明明白白显示在url上,而且页面刷新后不会丢失(因为url本身带着这些信息)。
举个和params的直观对比例子:假设做一个用户页面,路径是/user
。
- 用params传参:得把路由配置成
/user/:id
(变成动态路由),此时url是/user/123
; - 用query传参:路由配置不用改,url是
/user?id=123
。
简单说,query是“附加”在url后面的参数,不影响路径结构;params是“嵌入”到路径里的参数,需要路由提前规划好动态段。
怎么用router-link传query参数?
大部分时候,我们用<router-link>
组件实现声明式导航,传query参数得用“对象语法”的to
属性。
实际例子:从首页跳商品列表页传参
假设要从首页跳转到商品列表页,同时传“分类ID”和“排序方式”两个参数,代码可以这么写:
<router-link :to="{ path: '/product-list', query: { categoryId: 3, sort: 'price-desc' } }" >查看数码产品</router-link>
点击后,url会变成/product-list?categoryId=3&sort=price-desc
,这里要注意3个点:
- 必须用
:to
(v-bind:to)绑定对象——因为要传动态的query参数; - 别用字符串语法硬拼url(比如
to="/product-list?categoryId=3"
)——遇到中文、特殊符号容易编码错误,对象语法更稳妥; - 路由配置不用改——不管
/product-list
的路由规则咋写,query参数都会被追加到url上。
编程式导航怎么传query参数?
如果是按钮点击、异步请求后跳转这类“命令式”场景,得用this.$router.push()
方法。
实际例子:点击“立即购买”跳订单页传参
用户点击“立即购买”按钮后,跳转到订单页并传商品ID和购买数量:
methods: { goToOrder() { this.$router.push({ path: '/order', query: { productId: this.product.id, count: this.buyCount } }) } }
跳转后url是/order?productId=1001&count=2
,这里也可以用路由的name来导航(更推荐,尤其是路由配置了name时):
// 假设路由配置:{ name: 'orderPage', path: '/order' } this.$router.push({ name: 'orderPage', query: { productId: this.product.id, count: this.buyCount } })
两种方式(path或name)都能传query,区别是name
是路由的“别名”,更灵活(比如以后路径改了,只要name不变,代码不用改),但要注意:不管用path还是name,query都会被正常追加到url上。
页面里怎么接收query参数?
到了目标页面(比如Order组件),要获取传过来的productId
和count
,得用this.$route.query
。
实际例子:在Order组件里取参数
在组件的生命周期钩子(比如mounted)或者方法里取参数:
export default { mounted() { const { productId, count } = this.$route.query; console.log('商品ID:', productId); // 输出类似 "1001" console.log('购买数量:', count); // 输出类似 "2" } }
这里一定要分清$router
和$route
:
$router
是VueRouter的实例,用来做“跳转操作”(push、replace、go等);$route
是当前活跃的路由信息对象,里面存着path、query、params、meta等数据,用来“读参数”。
要是写错成this.$router.query
,控制台会报错“undefined”,因为$router根本没有query这个属性~
query参数刷新后还在吗?
很多同学担心页面刷新后参数丢了,这里明确说:query参数因为是拼在url上的,所以刷新后还在。
原理&测试场景
浏览器刷新页面时,会把当前url发给服务器,服务器返回页面后,Vue Router会解析url里的query参数,所以this.$route.query
还能拿到之前的值。
举个测试场景:在商品列表页用query传了categoryId=3
,跳转到列表页后刷新浏览器,url还是/product-list?categoryId=3
,mounted里打印this.$route.query.categoryId
,依然能拿到3。
但如果是用params传参(且路由没配置动态段),刷新后就会丢失——因为params没被放到url里,属于“内存级”参数,这也是query和params的核心差异之一。
怎么清除query参数?
有时候跳转后想把之前的query参数清空,比如从商品详情页回到列表页,不需要保留之前的筛选条件,这时候可以在跳转时给query传空对象。
实际例子:从详情页跳回列表页清空参数
从详情页跳回列表页时,清空所有query参数:
this.$router.push({ path: '/product-list', query: {} // 清空所有query参数 })
这样url就会变成/product-list
(没有后面的内容),如果只想清除部分参数,比如保留categoryId
但清除sort
,可以传{ categoryId: this.$route.query.categoryId, sort: '' }
,不过更推荐传需要保留的参数,避免遗漏。
query参数的类型有限制吗?
有同学尝试传对象、数组,发现url里变成了[object Object]
或者逗号分隔的字符串,这是因为url只能存储字符串类型的参数,Vue Router会自动把非字符串参数转成字符串(比如数字转字符串没问题,但对象会被转成[object Object]
)。
问题复现&解决方法
比如传这样的query:
this.$router.push({ path: '/test', query: { info: { name: '小明', age: 18 }, hobbies: ['篮球', '游戏'] } })
url会变成/test?info=[object%20Object]&hobbies=篮球,游戏
,接收的时候info
是字符串"[object Object]"
,hobbies
是字符串"篮球,游戏"
,根本没法用。
解决方法:把复杂数据转成JSON字符串
// 传参时 const infoStr = JSON.stringify({ name: '小明', age: 18 }); const hobbiesStr = JSON.stringify(['篮球', '游戏']); this.$router.push({ path: '/test', query: { info: infoStr, hobbies: hobbiesStr } }) // 接收时 mounted() { const info = JSON.parse(this.$route.query.info); const hobbies = JSON.parse(this.$route.query.hobbies); console.log(info.name); // 小明 console.log(hobbies[0]); // 篮球 }
这样就能完美传递对象、数组这类复杂数据了~ 简单类型(字符串、数字、布尔)直接传就行,Vue Router会帮你处理编码和解码。
和params参数的核心区别有哪些?
为了让大家更直观理解,列个对比表:
对比项 | query参数 | params参数 |
---|---|---|
传参方式 | path或name配合query对象 | 必须用name(用path传会被忽略) |
url显示 | 在url中以?key=value 形式显示 |
若路由配置了动态段(如/user/:id ),则显示在路径中;否则不显示 |
刷新保留 | 刷新后参数还在(因为url包含) | 若路由配置了动态段且url显示了参数,刷新保留;否则刷新丢失 |
路由配置依赖 | 不需要在路由规则里提前定义 | 若要在url显示参数,必须在路由path中定义动态段(如/user/:id ) |
参数隐藏性 | 参数暴露在url上,适合公开分享 | 若路由没配动态段,参数不暴露在url,适合传隐私数据 |
实际场景对比
- 做“商品搜索页”,筛选条件(价格区间、销量排序)适合用query——因为用户可能想把筛选后的链接分享给朋友,query参数在url里,分享后对方打开是一样的结果;
- 做“用户个人中心”,用户ID这类参数适合用params+动态路由(如
/user/:userId
)——因为每个用户的页面路径是唯一的,且ID放在路径里更符合RESTful风格,同时刷新也不会丢。
实战中哪些场景适合用query?
理解了query的特性,这些场景用query会很顺手:
列表页→详情页传ID
比如电商系统中,从商品列表点进商品详情,传商品ID,因为详情页需要根据ID请求接口拿数据,刷新后url里的ID还在,能重新请求数据,用户体验更稳。
搜索页的筛选条件
比如知乎的搜索页,筛选“综合、最新、最多赞同”,这些筛选条件会被拼到query里(如?type=latest&page=2
),用户刷新页面,筛选条件还在;分享链接给别人,对方打开也是同样的筛选结果。
分页功能
列表页的页码(page=3
)用query传,用户刷新后还在当前页,不会回到第一页,如果用params传(且路由没配动态段),刷新就会丢页码,体验很差。
多tab切换的状态保存
比如后台管理系统的选项卡,当前激活的tab(tab=order
)用query存,刷新后tab状态不变,不用用户重新点。
这些场景的共同点是:参数需要“持久化”(刷新或分享后不变),且不需要隐藏参数,用query再合适不过。
常见错误和解决办法
学的时候难免踩坑,把高频错误和解决方法列出来,避坑效率更高:
错误:传了query但url没变化
原因:可能用了path传参却错误地写了params(params和path一起用会被Vue Router忽略),或者to的对象语法写错了。
解决:检查to的对象里是不是用了params
而不是query
,确保是query: { ... }
。
错误:接收不到query参数
原因:把this.$route.query
写成了this.$router.query
(混淆了$route和$router)。
解决:route是“当前路由信息”,用来读参数;$router是“路由实例”,用来做跳转,接收参数一定用this.$route.query
。
错误:复杂数据传过去变成[object Object]
原因:url只能存字符串,对象、数组这类复杂类型直接传会被强制转成字符串,导致信息丢失。
解决:传参前用JSON.stringify
转成字符串,接收时用JSON.parse
转回来。
错误:刷新后query参数丢失
原因:极大概率是把query参数当成params传了(比如路由没配动态段,却用params传参),或者传参时没把query放到url里。
解决:确认传参方式是query,且用path或name配合query对象传参,确保url里有后的参数。
写在最后
Vue2 Router的query参数看似简单,实际涉及传参、接收、类型处理、和params的区别等多个细节,把这些知识点吃透,不管是做页面跳转传参,还是处理刷新、分享等场景,都能游刃有余,如果还有其他疑问,评论区留言,咱们一起讨论~
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。