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

一、先搞懂vue router里的params是干啥的?

terry 7小时前 阅读数 11 #Vue
文章标签 params

在Vue项目开发里,经常遇到需要根据不同数据渲染页面的情况,比如商品详情页要根据商品ID展示不同内容、用户个人页要根据用户ID加载信息,这时候vue router的params参数就派上用场了!可vue router with params到底咋用?从路由配置到传参、接收,再到避坑,今天一次性讲明白~

params是Vue Router里用来传递动态路由参数的机制,和URL里看得见的query参数(name=xxx)不一样,params更像“藏在路由结构里”的参数,举个更具体的例子:你做一个博客系统,文章详情页需要根据文章ID展示内容,如果用query,URL会是/article?articleId=1,但用params+动态路由,URL是/article/1,后者不仅URL更美观,SEO友好度也更高(搜索引擎更喜欢语义化的路径),而且从产品逻辑来说,文章ID是访问文章详情的必要条件,放在路由的动态段里,也能让路由配置更严谨——如果用户直接输/article(没有ID),路由匹配不到,会跳404或者重定向,避免无效访问。

配置带params的路由规则,得这么写!

路由配置文件(比如router/index.js)是整个路由系统的“规则手册”,要让params生效,得先在规则里留好“位置”。

错误示范:如果路由配置写成这样,params根本没地方放:

const routes = [
  {
    path: '/user',
    name: 'User',
    component: User
  }
]

这时就算传params: { id: 123 },URL还是/user,params也传不过去——因为路由规则里没有给params留动态段。

正确示范必须加动态段(用开头的字段):

const routes = [
  {
    name: 'User', // 路由命名很重要,后面传参要用到
    path: '/user/:id', // :id就是给params留的位置,代表用户ID
    component: User
  }
]

这样一来,当访问/user/123时,123会被自动解析成params里的id值,要是需要多个参数,比如订单ID和详情ID,路由可以写成/order/:orderId/detail/:detailId,对应params里就有orderIddetailId两个字段,命名和后续传参、接收保持一致就行~

用<router-link>声明式导航传params

在页面里写跳转链接(比如用户列表里的“查看主页”按钮),用<router-link>这种声明式导航最方便,核心是给to绑定一个对象,用name匹配路由,再用params传参。

举个实际例子:用户列表页面里,每个用户项对应一个跳转链接:

<template>
  <div class="user-list">
    <div v-for="user in userList" :key="user.id">
      <router-link 
        :to="{ 
          name: 'UserDetail', // 必须和路由配置的name一致
          params: { id: user.id } // 把用户ID传给详情页
        }"
      >
        {{ user.name }}的个人主页
      </router-link>
    </div>
  </div>
</template>
<p><script>
export default {
data() {
return {
userList: [
{ id: 1, name: '小明' },
{ id: 2, name: '小红' }
]
}
}
}
</script>

点击“小明的个人主页”,URL会变成/user/1,对应的UserDetail组件就能拿到params里的id啦~这里要注意:必须用name匹配路由,不能用path!如果改成path: '/user/:id'再传params,Vue Router会直接忽略params,传参失败。

用router.push编程式导航传params

如果是点击按钮、触发方法后跳转(查看当前用户主页”按钮),就得用编程式导航(router.push),Vue2和Vue3的写法略有不同,但核心逻辑一样:用name匹配路由,params传参。

Vue2写法(选项式API):

<template>
  <button @click="goToCurrentUser">查看我的主页</button>
</template>
<p><script>
export default {
data() {
return {
currentUserId: 123 // 假设从登录态拿到用户ID
}
},
methods: {
goToCurrentUser() {
this.$router.push({
name: 'UserDetail', // 路由的name
params: { id: this.currentUserId } // 传用户ID
})
}
}
}
</script>

Vue3写法(组合式API):需要先引入useRouter

<template>
  <button @click="goToCurrentUser">查看我的主页</button>
</template>
<p><script setup>
import { useRouter } from 'vue-router'
const router = useRouter()
const currentUserId = 123 // 假设从Pinia或sessionStorage拿到
const goToCurrentUser = () => {
router.push({
name: 'UserDetail',
params: { id: currentUserId }
})
}
</script>

点击按钮后,路由会跳转到/user/123,params里的id就被成功携带啦~同样要记住:必须用name,不能用path,否则params传不过去!

组件里咋接收params?分Vue2和Vue3说

不管是Vue2还是Vue3,接收params都要从当前路由对象里拿(不是操作路由的实例哦),Vue2用$route,Vue3用useRoute

Vue2组件接收(选项式API):

export default {
  mounted() {
    const userId = this.$route.params.id // 拿到路由里的id参数
    this.fetchUserData(userId) // 发请求拿用户信息
  },
  methods: {
    fetchUserData(id) {
      // 模拟接口请求
      axios.get(`/api/user/${id}`).then(res => {
        this.userInfo = res.data
      })
    }
  }
}

Vue3组件接收(组合式API):需要引入useRoute

<script setup>
import { onMounted } from 'vue'
import { useRoute } from 'vue-router'
import axios from 'axios'
<p>const route = useRoute()
const userInfo = ref({})</p>
<p>onMounted(() => {
const userId = route.params.id
fetchUserInfo(userId)
})</p>
<p>const fetchUserInfo = (id) => {
axios.get(<code>/api/user/${id}</code>).then(res => {
userInfo.value = res.data
})
}
</script>

如果路由配置里有多个动态参数(比如/order/:orderId/detail/:detailId),接收时就是route.params.orderIdroute.params.detailId,按需取值就行~

动态路由匹配:params和组件复用的坑

当多个不同的路由对应同一个组件时(比如/user/123/user/456都渲染User组件),Vue为了性能会复用组件——这意味着组件的生命周期钩子(比如created、mounted)不会重新执行!举个场景:做电商APP的商品列表,点击商品A(/product/1)跳转到详情页,再点商品B(/product/2),如果不处理,详情页还是商品A的内容,因为组件没销毁,生命周期没重新走。

解决方法分Vue2和Vue3:

▎Vue2:用watch监听$route变化

export default {
  data() {
    return {
      productInfo: {}
    }
  },
  mounted() {
    this.fetchProduct(this.$route.params.productId)
  },
  watch: {
    // 监听params里的productId变化
    '$route.params.productId'(newId) {
      this.fetchProduct(newId)
    }
  },
  methods: {
    fetchProduct(id) {
      // 发请求拿商品信息
    }
  }
}

▎Vue3:用onBeforeRouteUpdate导航守卫

<script setup>
import { onBeforeRouteUpdate, onMounted } from 'vue'
import { useRoute } from 'vue-router'
import axios from 'axios'
<p>const route = useRoute()
const productInfo = ref({})</p>
<p>const fetchProduct = (id) => {
axios.get(<code>/api/product/${id}</code>).then(res => {
productInfo.value = res.data
})
}</p>
<p>onMounted(() => {
fetchProduct(route.params.productId)
})</p>
<p>// 路由更新前执行,拿到新的productId
onBeforeRouteUpdate((to) => {
fetchProduct(to.params.productId)
})
</script>

这样不管是首次进入还是切换路由,都能拿到最新的参数,请求对应数据,页面就会正确更新~

用params传参的注意事项,避坑必看!

用params时踩过的坑不少,这几个点一定要注意:

刷新页面,params可能丢失

如果路由配置里没有动态路由(比如path是/user,不是/user/:id),只是通过name传params,刷新页面后params会直接消失!因为params本质是“基于路由名传递的内存参数”,没被编码到URL里。

解决方法

  • 把参数放到动态路由里(推荐):路由配置写成/user/:id,这样URL里有id,刷新也能保留。
  • 用sessionStorage暂存:传参时把params存到sessionStorage,组件里优先从$route.params拿,拿不到再从sessionStorage取。
// 传参时存
this.$router.push({ name: 'User', params: { id: 123 }})
sessionStorage.setItem('currentUserId', 123)
<p>// 组件里取
mounted() {
const userId = this.$route.params.id || sessionStorage.getItem('currentUserId')
this.fetchUserData(userId)
}

但要注意sessionStorage的清除逻辑,避免数据混乱~

传参时,name和path别搞混

很多新手会犯的错:路由配置有name,传参时却用path。

this.$router.push({
  path: '/user', // 错误!用path的话params传不过去
  params: { id: 123 }
})

这时URL还是/user,params根本没传过去。params是和路由的name绑定的,必须用name传参

params和query能一起用吗?

完全可以!比如做带筛选的用户列表,用户ID是必须的(params),筛选条件是可选的(query),路由配置:

const routes = [
  {
    name: 'UserFilter',
    path: '/user/:id/filter',
    component: UserFilter
  }
]

传参时:

this.$router.push({
  name: 'UserFilter',
  params: { id: 123 },
  query: { gender: 'male', age: 20 }
})

这时URL是/user/123/filter?gender=male&age=20,params里有id,query里有筛选条件,组件里分别拿$route.params.id$route.query.gender就行~

路由参数的可选匹配

如果想让参数可选(比如用户主页可以带ID,也可以不带),路由配置加问号:

const routes = [
  {
    name: 'User',
    path: '/user/:id?', // ?表示id可选
    component: User
  }
]

访问/user时,params.id是undefined;访问/user/123时,params.id是123,组件里要处理id为undefined的情况,比如展示默认页面~

就是vue router with params的核心用法和避坑指南啦!从路由配置、传参到接收,再到处理组件复用和参数丢失,把这些点吃透,开发中遇到动态参数需求就不会慌啦~要是还有疑问,评论区随时喊我~

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

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

热门