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

Vue2 里怎么获取路由参数?

terry 6小时前 阅读数 8 #Vue
文章标签 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 里的 categorypage,这种参数适合做筛选、分页这类「可选」或「多条件」的场景——即使不传,页面也能正常访问。

在 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),这时候组件的 createdmounted 这些生命周期钩子不会重新执行,导致参数更新了但页面数据没变化,这时候得主动监听参数变化。

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

发表评论:

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

热门