1.Vue Router里的query传参是干啥的?
不少刚学Vue的朋友,在处理页面跳转传参时,对query传参总是有点懵——什么时候用query?怎么在路由里传和接?和params传参有啥不一样?今天就用问答的方式,把Vue Router query传参的关键知识点拆明白,不管是新手入门还是想巩固细节,看完心里都有数~
简单说,query传参是把参数“挂”在URL的查询字符串里,格式像 `?key1=value1&key2=value2` 这样,它的核心作用是**在不同页面间传递公开的、需要保留的状态**。举个实际场景:做电商列表页时,用户选了“价格从低到高”“销量优先”这些筛选条件,或者分页到第3页,把这些条件存在query里,不仅跳转详情页再返回时能保留筛选状态,用户把这个带参数的URL分享给朋友,对方打开也能看到一样的筛选结果,而且刷新页面时,因为参数在URL里,数据也不会丢~
怎么用query传参跳转页面?
Vue Router里跳转分声明式导航(用 <router-link>
组件)和编程式导航(用 this.$router.push
这类API),两种方式传query参数的逻辑差不多,看你习惯哪种。
声明式导航(<router-link>
)
直接在 :to
里写一个对象,包含 path
(或 name
)和 query
字段,比如从商品列表跳转到详情页,带商品ID:
<router-link :to="{ path: '/product/detail', query: { productId: 123, tab: 'info' } }" > 查看商品详情 </router-link>
点击后,URL会变成 /product/detail?productId=123&tab=info
。
编程式导航(this.$router.push
)
在JS里通过路由实例的 push
方法跳转,同样传包含 path
/name
和 query
的对象,比如在按钮点击事件里写:
methods: { goDetail() { this.$router.push({ path: '/product/detail', query: { productId: this.productId, tab: 'info' } }) } }
如果用组合式API(Vue 3 + Setup语法),需要先导入 useRouter
:
import { useRouter } from 'vue-router' const router = useRouter() const goDetail = () => { router.push({ path: '/product/detail', query: { productId: 123, tab: 'info' } }) }
目标页面怎么接收query参数?
参数传过去后,目标页面(组件)得“接住”这些参数才能用,分两种写法:选项式API 和 组合式API。
选项式API(Vue 2 或 Vue 3 选项式风格)
直接通过 this.$route.query
拿参数,比如在商品详情组件的 created
钩子(或其他生命周期)里处理:
export default { created() { const { productId, tab } = this.$route.query console.log('商品ID:', productId) // 输出 "123"(注意是字符串,除非传数字要自己转) console.log('当前tab:', tab) // 输出 "info" // 调用接口拿商品详情:this.getProductDetail(productId) } }
组合式API(Vue 3 Setup语法)
需要导入 useRoute
来获取当前路由信息:
import { useRoute } from 'vue-router' export default { setup() { const route = useRoute() // 可以在onMounted或直接用watch监听query变化 const productId = route.query.productId const tab = route.query.tab console.log('商品ID:', productId) return { productId, tab } } }
⚠️ 注意:URL里的参数都是字符串!如果传的是数字(productId: 123
),接收时 route.query.productId
是 "123"
,要转成数字得自己用 Number()
处理~
query传参后,URL显示有啥特点?能藏起来吗?
query参数的核心特点就是“显式”在URL里,用户能直接看到 ?key=value
这种结构,这意味着:
- 适合传公开、不需要保密的参数(比如筛选条件、分页号);
- 不适合传敏感信息(比如用户token、密码),因为URL能被复制、分享,敏感信息暴露风险高;
- 想“藏”参数?别用query!如果参数不想在URL显示,考虑用
params
传参(但params有刷新丢数据的风险,后面对比会讲)。
如果传的是对象或数组,Vue Router会自动帮你做URL编码(比如传 { info: { a: 1, b: 2 } }
,URL里会变成 info=%7B%22a%22%3A1%2C%22b%22%3A2%7D
),接收时要解析的话,得用 JSON.parse(route.query.info)
,但要注意参数可能不存在,得加容错:
const infoStr = route.query.info const info = infoStr ? JSON.parse(infoStr) : {}
query传参刷新页面会丢数据吗?
不会!因为参数存在URL里,刷新页面时浏览器会保留URL的查询字符串,this.$route.query
里的参数也能保留。
对比一下 params
传参(如果没用动态路由的话):比如用 this.$router.push({ name: 'xxx', params: { id: 123 } })
,但路由配置没写 /xxx/:id
,这时候参数不在URL里,刷新页面就没了,所以如果需求是“刷新不丢参数”,优先选query~
query和params传参核心区别是啥?
很多人分不清这俩,直接列关键差异点,以后遇到场景能快速选:
对比维度 | query传参 | params传参(非动态路由场景) |
---|---|---|
URL表现 | 参数在后(如?a=1&b=2 ) |
参数不在URL里(除非配了动态路由) |
刷新稳定性 | 刷新不丢参数 | 刷新后参数丢失(没配动态路由时) |
传参方式 | path/name都能配query | 建议用name(用path会忽略params) |
使用场景 | 公开、需保留、可分享的参数 | 私密、不需要暴露在URL的参数 |
举个场景例子:做“用户订单列表”,订单状态筛选(全部/待支付/已完成)适合用query(URL带状态参数,分享链接能直接看到筛选结果);而订单详情页的“订单ID”如果用动态路由(/order/:orderId
),这时候用params传参(因为ID在URL路径里,属于动态路由匹配),这种情况params刷新也不丢~
传参时参数是null/undefined会怎样?
测试一下就懂:
- 传
null
:URL里会显示?key=null
(query: { tab: null }
,URL变成?tab=null
); - 传
undefined
:该参数会从URL里消失(比如原来URL有?tab=info
,现在传query: { tab: undefined }
,URL里tab参数就没了)。
所以如果想“清空”某个query参数,可以传 undefined
,或者在对象里删除该属性。
// 只保留page,删掉tab const { query } = this.$route this.$router.push({ query: { ...query, tab: undefined } // 或者用delete query.tab(但要注意对象引用) })
多个路由共用query参数咋处理?
比如后台管理系统,多个页面都需要“分页页码(page)”和“每页条数(size)”,总不能每个页面都单独传一遍吧?可以用全局状态管理(比如Vuex、Pinia)+ query参数同步。
思路:在Pinia里存一个全局的 pageParams
状态,包含page和size,每次页面跳转时,把Pinia里的参数同步到query里;页面加载时,再把query里的参数同步回Pinia,这样多个页面共用一套参数,维护起来更方便~
代码示例(Pinia伪代码):
// store/page.js import { defineStore } from 'pinia' export const usePageStore = defineStore('page', { state: () => ({ page: 1, size: 10 }), actions: { setPageParams(query) { this.page = query.page ? Number(query.page) : 1 this.size = query.size ? Number(query.size) : 10 } } }) // 目标页面组件 import { usePageStore } from '@/store/page' import { useRoute, useRouter } from 'vue-router' export default { setup() { const pageStore = usePageStore() const route = useRoute() const router = useRouter() // 页面加载时,把query参数同步到store pageStore.setPageParams(route.query) // 分页变化时,同步到query和store const handlePageChange = (newPage) => { pageStore.page = newPage router.push({ query: { ...route.query, page: newPage } }) } return { handlePageChange } } }
怎么修改已有的query参数?
比如当前URL是 /list?page=1&size=10
,想把page改成2,同时保留size参数,这时候要“合并”原有参数,避免直接覆盖导致其他参数丢失。
用扩展运算符()把原来的query展开,再覆盖要修改的字段:
const { query } = this.$route this.$router.push({ query: { ...query, page: query.page + 1 } })
这样URL就会变成 /list?page=2&size=10
,其他参数(比如size)还在~
SEO友好度上,query传参有帮助吗?
对需要SEO(搜索引擎优化)query传参很友好!因为搜索引擎爬虫抓取页面时,会把URL里的query参数当作“不同页面状态”来识别。
比如做博客的“标签列表页”,URL是 /blog?tag=前端
和 /blog?tag=后端
,搜索引擎能区分这是两个不同的页面,分别收录,但如果用params传参且参数不在URL里,爬虫就识别不出差异,不利于SEO,所以做面向搜索引擎的页面,优先用query传参暴露关键参数~
看完这10个问题,再遇到Vue Router query传参的需求,应该能精准判断场景、熟练写代码了吧?记住核心逻辑:query是URL可见的“公开传参王”,刷新不丢、适合分享和SEO,传参接参分声明式和编程式,和params的区别要根据场景选,多在项目里练几次,这些知识点自然就吃透啦~
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。