Vue2 里怎么获取路由参数?
在开发 Vue2 项目时,路由参数的获取是很基础又关键的操作,不管是做详情页根据 ID 加载数据,还是通过查询参数做页面筛选,都得先把路由里的参数拿到手,那 Vue2 里到底怎么获取不同类型的路由参数?不同场景下有啥要注意的地方?这篇文章就用问答的形式,把常见情况拆解开来讲明白。
动态路由参数(params)怎么拿?
动态路由参数是路由路径里用 :参数名
定义的可变部分,比如做用户详情页时,不同用户对应不同 ID,路由配置可能长这样:
// router/index.js import Vue from 'vue' import Router from 'vue-router' import UserDetail from '@/components/UserDetail' Vue.use(Router) export default new Router({ routes: [ { path: '/user/:id', // 这里的:id就是动态参数 component: UserDetail } ] })
在 UserDetail
组件里,通过 this.$route.params
就能拿到参数,比如在组件的 created
生命周期钩子中写:
export default { created() { const userId = this.$route.params.id console.log('当前用户ID:', userId) // 拿着userId调接口拿用户信息 } }
但有个关键细节:如果从 /user/1
跳到 /user/2
,组件实例会被复用(因为路由对应的组件还是 UserDetail
),这时候 created
这类生命周期钩子不会重新执行,参数变化了怎么感知?这时候得用 watch
监听 $route
的变化:
export default { watch: { '$route'(to, from) { // to是目标路由对象,from是来源路由对象 const newId = to.params.id const oldId = from.params.id if (newId !== oldId) { this.fetchUserInfo(newId) // 重新请求数据 } } }, methods: { fetchUserInfo(id) { // 调接口逻辑 } } }
跳转动态路由时,除了用字符串拼接路径(this.$router.push('/user/123')
),还能通过 name + params
的方式:
this.$router.push({ name: 'UserDetail', // 路由配置里的name要和规则对应 params: { id: 123 } })
这种方式下,params
里的参数会被解析到 $route.params
里,但要注意:如果用 path
跳转,params
会被忽略,{ path: '/user', params: { id: 123 }}
这样写是无效的,必须用 name
配合 params
才行~
查询参数(query)怎么获取?
查询参数是 URL 里 后面的键值对,/goods?category=electronics&page=1
里的 category
和 page
,这种参数适合做筛选、分页这类「可选」或「多条件」的场景——即使不传,页面也能正常访问。
在 Vue2 里,查询参数通过 this.$route.query
获取,先看路由配置(查询参数不需要在 path
里定义,跳转时加就行):
// router/index.js { path: '/goods', component: GoodsList }
然后在 GoodsList
组件里拿参数:
export default { created() { const category = this.$route.query.category const page = this.$route.query.page console.log('当前分类:', category, '当前页码:', page) this.fetchGoods(category, page) }, methods: { fetchGoods(category, page) { // 根据分类和页码请求商品列表 } } }
跳转查询参数的方式很灵活,用 router-link
或者 this.$router.push
都可以:
<!-- router-link方式 --> <router-link :to="{ path: '/goods', query: { category: 'electronics', page: 2 } }">跳转到第二页电子产品</router-link> <!-- js跳转方式 --> this.$router.push({ path: '/goods', query: { category: 'clothes', page: 1 } })
查询参数有个明显特点:刷新页面后参数不会消失(因为存在 URL 里),而动态路由参数(params)如果通过 path
跳转传参,刷新后会丢失(除非用 name + params
,但此时参数不在 URL 里,刷新也会丢),所以如果需要参数持久化(比如分享链接带筛选条件),优先用 query
;如果是页面唯一标识(比如用户 ID),用动态路由 params
更合适~
路由元信息(meta)里的参数咋取?
路由元信息(meta)是给路由附加「自定义信息」的地方,常见场景比如:判断页面是否需要登录权限、设置页面标题、标记页面类型等,它不需要在 URL 里体现,属于路由的「隐藏属性」。
先看路由配置里怎么加 meta
:
// router/index.js { path: '/order', component: Order, meta: { requireAuth: true, // 需要登录 '我的订单' // 页面标题 } }, { path: '/home', component: Home, meta: { requireAuth: false, '首页' } }
在组件里获取 meta
信息,用 this.$route.meta
就行,比如做全局权限拦截,在路由守卫里判断:
// 全局前置守卫 router.beforeEach((to, from, next) => { if (to.meta.requireAuth) { // 检查是否登录,比如从store里拿token const isLogin = localStorage.getItem('token') if (isLogin) { next() } else { next('/login') // 没登录跳登录页 } } else { next() } })
在组件内部,也能直接用 meta
做逻辑,比如设置页面标题:
export default { created() { document.title = this.$route.meta.title } }
meta
的优势是「解耦」——把路由相关的额外信息集中在路由配置里,不用散落在各个组件,而且获取方式很直接,不用关心 URL 结构,适合存一些和业务逻辑相关但不需要暴露在 URL 的信息~
路由参数变了,组件没重新渲染咋处理?
前面讲动态路由时提到过,路由参数变化但组件复用(/user/1 → /user/2
),这时候组件的 created
、mounted
这些生命周期钩子不会重新执行,导致参数更新了但页面数据没变化,这时候得主动监听参数变化。
watch 监听 $route
在组件里用 watch
监听 $route
的变化,参数改变时执行逻辑:
export default { data() { return { userInfo: {} } }, watch: { '$route'(to) { const newId = to.params.id this.fetchUser(newId) // 重新请求数据 } }, created() { this.fetchUser(this.$route.params.id) }, methods: { fetchUser(id) { // 调接口获取用户信息,更新userInfo } } }
使用导航守卫 beforeRouteUpdate
Vue2 提供了组件内的导航守卫 beforeRouteUpdate
,它会在当前组件对应的路由参数变化时触发(组件复用的情况):
export default { data() { return { userInfo: {} } }, beforeRouteUpdate(to, from, next) { const newId = to.params.id this.fetchUser(newId) next() // 必须调用next()才能继续导航 }, created() { this.fetchUser(this.$route.params.id) }, methods: { fetchUser(id) { // 调接口逻辑 } } }
这两种方式选哪个?如果只是简单的参数变化后请求数据,watch
更简洁;如果需要更细粒度控制导航流程(比如判断是否允许跳转),用 beforeRouteUpdate
更合适~
有没有更“ Vue 风格”的获取方式?
很多同学觉得直接用 this.$route
有点「命令式」,想结合 Vue 的响应式特性做优化,这时候可以用计算属性把路由参数包一层,让代码更简洁、易维护。
比如动态路由参数的场景:
export default { computed: { userId() { return this.$route.params.id } }, watch: { userId(newId) { this.fetchUser(newId) } }, created() { this.fetchUser(this.userId) }, methods: { fetchUser(id) { // 调接口逻辑 } } }
这样做的好处是,userId
变成了响应式数据,不管是初始加载还是参数变化,都能自动触发逻辑,而且代码里不用到处写 this.$route.params.id
,后期如果路由参数结构变了(比如从 params.id
改成 params.userId
),只需要改计算属性里的逻辑,其他地方不用动,维护性更强。
如果多个组件都需要获取同一种路由参数,还能封装成混入(mixin)或者自定义指令,不过这种场景比较少,大部分时候计算属性就够解决「Vue 风格」的需求啦~
Vue2 里获取路由参数主要分这几种场景:动态路由用 $route.params
、查询参数用 $route.query
、元信息用 $route.meta
,不同场景要注意参数的特性(比如刷新是否保留、组件复用怎么处理),还要结合 watch
或导航守卫来应对参数变化的情况,实际开发中,先想清楚业务需求(需不需要参数在 URL 里、要不要持久化、组件复用咋处理),再选对应的参数类型和获取方式,代码才能既灵活又健壮~要是你在开发中遇到路由参数相关的坑,评论区聊聊,咱们一起解决~
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。