Code前端首页关于Code前端联系我们

1.Vue Router里的query传参是干啥的?

terry 7小时前 阅读数 9 #Vue

不少刚学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/namequery 的对象,比如在按钮点击事件里写:

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=nullquery: { 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前端网发表,如需转载,请注明页面地址。

发表评论:

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

热门