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

vue router怎么获取url?

terry 3小时前 阅读数 5 #Vue
文章标签 vue router;获取url

做Vue项目时,经常需要和当前页面的URL“打交道”——比如判断用户进了哪个页面、从URL里抠参数发请求、根据搜索关键词展示内容…但Vue Router的URL信息藏在哪?不同场景(组件内、组件外、动态路由、查询参数)咋获取?这篇从基础到实战,把常见情况拆明白~

组件里咋拿到当前路由信息?

先分Vue2和Vue3两种情况(毕竟API有差异),核心是用路由实例提供的“路由对象”,里面存着当前URL的所有信息~

Vue3(组合式API):用 useRoute

在组件的<script setup>里,先导入useRoute,它会返回一个响应式的路由对象(能自动跟踪路由变化),路由对象里有这些关键属性:

  • path:当前路径(不含查询参数、哈希,比如/user/123
  • params:动态路由参数(后面讲动态路由时细说)
  • query:查询参数(后面的部分,比如?name=jack对应{name: 'jack'}
  • fullPath:完整URL(包含路径、查询、哈希,比如/user/123?name=jack#info
  • name:路由配置里的name(如果配了的话)

举个实际例子,假设当前URL是/product/1001?tab=detail,组件里这么写:

<template>
  <div>
    路径:{{ route.path }} → 输出 /product/1001<br>
    完整路径:{{ route.fullPath }} → 输出 /product/1001?tab=detail<br>
    动态参数:{{ route.params }} → 输出 {productId: '1001'}(假设路由是/product/:productId)<br>
    查询参数:{{ route.query.tab }} → 输出 detail
  </div>
</template>
<script setup>
import { useRoute } from 'vue-router' // 从vue-router导入useRoute
const route = useRoute() // 获取路由对象
</script>

Vue2(选项式API):用 this.$route

在Vue2的组件里,不需要额外导入,直接通过this.$route访问路由对象,属性和Vue3的route一致。

<template>
  <div>当前路径:{{ $route.path }}</div>
</template>
<script>
export default {
  mounted() {
    console.log(this.$route.query) // 打印查询参数对象
  }
}
</script>

动态路由参数咋提取?

动态路由是指URL里带变量的部分,比如用户详情页需要根据不同用户ID跳转,路由配置成path: '/user/:userId':userId就是动态参数),这时候要从URL里把userId抠出来~

步骤:路由配置→组件里拿参数

  1. 先在路由规则里定义动态参数:
    const routes = [
    {
     path: '/user/:userId', // :userId是动态参数
     component: UserDetail
    }
    ]
  2. 组件里通过route.params.参数名获取:
    Vue3写法:
    <script setup>
    import { useRoute } from 'vue-router'
    const route = useRoute()
    const userId = route.params.userId // 当URL是/user/666时,userId就是'666'
    </script>

    Vue2写法:

    export default {
    mounted() {
     const userId = this.$route.params.userId
    }
    }

特殊情况:可选参数、正则限制

  • 可选参数:如果参数可传可不传,路由配置写成path: '/user/:userId?',此时route.params.userId可能是undefined(没传的时候)。
  • 正则限制:想让参数只能是数字?路由配置写成path: '/user/:userId(\\d+)',这样只有当userId是数字时,路由才匹配(比如/user/123有效,/user/abc无效)。

查询参数(?xxx=yyy)咋获取?

查询参数是URL中后面的键值对(比如/search?keyword=vue&page=2),这部分信息存在route.query里,它是个对象,键是参数名,值是参数值~

基本用法

假设当前URL是/search?keyword=vue&page=2,组件里:
Vue3:

<script setup>
import { useRoute } from 'vue-router'
const route = useRoute()
const keyword = route.query.keyword // 输出 'vue'
const page = Number(route.query.page) // 输出 2(转成数字)
</script>

Vue2:

export default {
  mounted() {
    console.log(this.$route.query.keyword) // 输出 'vue'
  }
}

多值参数处理

如果URL是/tags?tag=js&tag=vue(同一个参数传多个值),route.query.tag会变成数组['js', 'vue'],处理时要注意类型,

const tags = Array.isArray(route.query.tag) 
  ? route.query.tag 
  : [route.query.tag] // 确保是数组,方便后续遍历

非组件环境咋拿路由信息?

有时候不在组件里(比如路由守卫、单独的工具函数),也要获取URL信息,这时候得换方法~

路由守卫里:用tofrom

全局守卫(比如beforeEach)、组件内守卫(比如beforeRouteEnter)会传入tofrom两个参数,它们都是路由对象,和$route结构一样~

举个全局守卫的例子(判断用户权限):

router.beforeEach((to, from) => {
  console.log('要进入的页面:', to.path) // /admin
  console.log('从哪个页面来:', from.fullPath) // /home?tab=news
  // 假设只有管理员能进/admin
  if (to.path === '/admin' && !isAdmin()) {
    return '/login' // 没权限就跳登录页
  }
})

组件内守卫(Vue2的beforeRouteEnter):

export default {
  beforeRouteEnter(to, from, next) {
    console.log('要进入的页面参数:', to.params.id)
    next() // 必须调用next()放行
  }
}

单独JS文件里:导入router实例

如果在工具函数、自定义插件里需要路由信息,得先导入项目里创建的router实例,再通过currentRoute获取~

Vue3中,router.currentRoute响应式对象(用ref包着),所以要取value

// 假设router.js里导出了router实例
import router from './router'
function getCurrentPage() {
  return router.currentRoute.value.path // 获取当前路径
}

Vue2中,router.currentRoute直接是路由对象:

import router from './router'
console.log(router.currentRoute.path) // 直接拿路径

path和fullPath有啥区别?啥时候用?

很多人分不清pathfullPath,其实它们的核心区别是是否包含查询参数和哈希

  • path:只包含“路由路径 + 动态参数”(比如/user/123)。
  • fullPath:包含完整的URL(路径 + 查询参数 + 哈希,比如/user/123?name=jack#info)。

用的场景举例

  • 导航栏高亮:判断“当前是否是首页”,用path === '/'就够(不管有没有查询参数,只要路径是/就高亮)。
  • 分享链接:需要把用户当前的完整URL发出去,就得用fullPath(比如用户在/search?keyword=vue,分享链接要包含查询参数)。
  • 埋点统计:记录用户的完整访问路径,fullPath更准确。

实战:根据URL参数加载数据

光说不练假把式,举两个常见场景,看怎么用URL参数干活~

场景1:文章详情页(动态路由参数)

需求:用户访问/article/1001时,用1001这个文章ID请求接口,渲染文章内容。

步骤:

  1. 配置动态路由:
    const routes = [
    {
     path: '/article/:articleId',
     component: ArticleDetail
    }
    ]
  2. 组件内获取参数并请求:
    <template>
    <div v-if="article">
     <h1>{{ article.title }}</h1>
     <p>{{ article.content }}</p>
    </div>
    </template>
```

场景2:列表页分页(查询参数)

需求:用户访问/list?page=2&size=10时,用pagesize做分页请求。

组件里这么写:

<template>
  <div>
    <ul>
      <li v-for="item in list" :key="item.id">{{ item.name }}</li>
    </ul>
  </div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { useRoute } from 'vue-router'
import { getList } from '@/api/list' // 假设的接口函数
const list = ref([])
const route = useRoute()
// 处理查询参数(转成数字,设置默认值)
const page = Number(route.query.page) || 1
const size = Number(route.query.size) || 10
onMounted(async () => {
  const res = await getList(page, size) // 发分页请求
  list.value = res.data
})
</script>

常见问题&避坑指南

Vue2和Vue3 API别搞混

  • Vue3组合式API:必须用useRoute(从vue-router导入)。
  • Vue3选项式API:可以用this.$route(和Vue2一样)。
  • Vue2:只能用this.$route

路由变化时,组件没销毁咋更新数据?

比如动态路由参数变了(/user/1/user/2),组件会复用(不销毁重建),这时候onMounted不会重新执行!得用watch监听路由变化

Vue3写法:

<script setup>
import { watch } from 'vue'
import { useRoute } from 'vue-router'
const route = useRoute()
watch(() => route.params.id, (newId) => {
  // newId变化时,重新请求数据
  fetchData(newId)
}, { immediate: true }) // immediate:页面加载时也执行一次
function fetchData(id) { /* ... */ }
</script>

Vue2写法:

export default {
  watch: {
    '$route.params.id'(newId) {
      this.fetchData(newId)
    }
  },
  methods: {
    fetchData(id) { /* ... */ }
  }
}

别直接修改$route!

$route只读对象,想改URL只能用router.pushrouter.replace这些方法,比如想跳转到新页面,得写:

import { useRouter } from 'vue-router'
const router = useRouter()
router.push('/new-path') // 正确
// this.$route.path = '/new-path' → 错误!会报错

Vue Router获取URL信息的核心是「路由对象」($route或useRoute返回的对象),不同场景下(组件内、组件外、动态路由、查询参数)的获取方式略有不同,但只要抓住「路由对象的属性」和「API版本差异」这两个点,就能轻松应对~ 下次遇到URL相关的需求,直接对应场景挑方法用就好啦~

版权声明

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

发表评论:

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

热门