Skip to content

useRoute | Vue Router API

概述

useRoute 是 Vue Router 的组合式 API 函数,用于在组件中访问当前路由信息。它返回一个响应式的路由对象,包含当前路由的各种详细信息。

语法

typescript
function useRoute(): RouteLocationNormalized

返回值

类型: RouteLocationNormalized说明: 当前路由的标准化信息对象,包含路径、参数、查询等信息

基本用法

在组件中访问路由信息

vue
<script setup>
import { useRoute } from 'vue-router'

const route = useRoute()

// 访问路由信息
console.log('当前路径:', route.path)
console.log('路由参数:', route.params)
console.log('查询参数:', route.query)
console.log('哈希值:', route.hash)
</script>

<template>
  <div>
    <p>当前页面: {{ route.path }}</p>
    <p>用户ID: {{ route.params.id }}</p>
    <p>搜索关键词: {{ route.query.q }}</p>
  </div>
</template>

路由对象属性

核心属性

path

类型: string说明: 当前路由的路径(不含查询参数和哈希)

javascript
// 对于 /users/123?page=2#section
route.path // '/users/123'

fullPath

类型: string说明: 完整路径(包含查询参数和哈希)

javascript
// 对于 /users/123?page=2#section
route.fullPath // '/users/123?page=2#section'

params

类型: Record<string, string | string[]>说明: 路由参数对象

javascript
// 对于路由 /users/:id/posts/:postId
route.params // { id: '123', postId: '456' }

query

类型: Record<string, string | string[]>说明: 查询参数对象

javascript
// 对于 /search?q=vue&category=docs
route.query // { q: 'vue', category: 'docs' }

hash

类型: string说明: 当前 URL 的哈希部分(带 #)

javascript
// 对于 /page#section
route.hash // '#section'

路由匹配信息

matched

类型: RouteRecordNormalized[]说明: 匹配的路由记录数组(用于嵌套路由)

javascript
route.matched.forEach(record => {
  console.log('匹配的路由:', record.path)
})

meta

类型: Record<string, any>说明: 路由元信息(合并了所有匹配路由的 meta)

javascript
// 访问路由元信息
if (route.meta.requiresAuth) {
  // 需要认证的逻辑
}

name

类型: string | symbol | undefined | null说明: 路由名称(如果定义了的话)

javascript
if (route.name === 'user-profile') {
  // 用户资料页的特殊逻辑
}

实际应用场景

场景 1:动态页面内容

vue
<script setup>
import { useRoute } from 'vue-router'
import { computed } from 'vue'

const route = useRoute()

// 基于路由参数动态加载内容
const userId = computed(() => route.params.id)
const pageTitle = computed(() => {
  if (route.name === 'user-profile') {
    return `用户 ${userId.value} 的资料`
  }
  return '默认标题'
})
</script>

<template>
  <div>
    <h1>{{ pageTitle }}</h1>
    <user-profile :user-id="userId" />
  </div>
</template>

场景 2:搜索和过滤功能

vue
<script setup>
import { useRoute } from 'vue-router'
import { watch, ref } from 'vue'

const route = useRoute()
const searchResults = ref([])

// 监听查询参数变化
watch(
  () => route.query,
  async (newQuery) => {
    if (newQuery.q) {
      // 执行搜索
      searchResults.value = await api.search(newQuery.q, newQuery)
    }
  },
  { immediate: true }
)

// 获取当前筛选条件
const currentFilters = computed(() => ({
  category: route.query.category,
  sort: route.query.sort || 'relevance',
  priceRange: route.query.priceRange
}))
</script>

场景 3:面包屑导航

vue
<script setup>
import { useRoute } from 'vue-router'
import { computed } from 'vue'

const route = useRoute()

// 生成面包屑数据
const breadcrumbs = computed(() => {
  return route.matched
    .filter(record => record.meta?.breadcrumb)
    .map(record => ({
      text: record.meta.breadcrumb,
      path: record.path,
      active: record === route.matched[route.matched.length - 1]
    }))
})
</script>

<template>
  <nav class="breadcrumb">
    <router-link 
      v-for="item in breadcrumbs" 
      :key="item.path"
      :to="item.path"
      :class="{ active: item.active }"
    >
      {{ item.text }}
    </router-link>
  </nav>
</template>

场景 4:权限和功能控制

vue
<script setup>
import { useRoute } from 'vue-router'
import { computed } from 'vue'

const route = useRoute()

// 基于路由元信息控制功能
const canEdit = computed(() => 
  route.meta.permissions?.includes('edit') ?? false
)

const showAdminPanel = computed(() => 
  route.meta.requiresAdmin && userStore.isAdmin
)

// 页面特定的样式类
const pageClass = computed(() => 
  `page-${route.name} theme-${route.meta.theme || 'light'}`
)
</script>

<template>
  <div :class="pageClass">
    <admin-panel v-if="showAdminPanel" />
    <edit-button v-if="canEdit" />
    <!-- 页面内容 -->
  </div>
</template>

高级用法

响应式路由监听

vue
<script setup>
import { useRoute } from 'vue-router'
import { watchEffect } from 'vue'

const route = useRoute()

// 自动响应路由变化
watchEffect(() => {
  // 当路由参数变化时重新加载数据
  if (route.params.id) {
    loadUserData(route.params.id)
  }
  
  // 更新页面标题
  if (route.meta.title) {
    document.title = `${route.meta.title} - 我的应用`
  }
  
  // 发送页面浏览统计
  analytics.trackPageView(route.fullPath)
})
</script>

路由参数类型转换

javascript
import { useRoute } from 'vue-router'
import { computed } from 'vue'

export function useRouteParams() {
  const route = useRoute()
  
  return {
    // 将字符串参数转换为数字
    userId: computed(() => parseInt(route.params.id) || 0),
    page: computed(() => parseInt(route.query.page) || 1),
    
    // 处理数组参数
    categories: computed(() => {
      const categoryParam = route.query.categories
      return Array.isArray(categoryParam) 
        ? categoryParam 
        : categoryParam ? [categoryParam] : []
    }),
    
    // 布尔参数处理
    isPreview: computed(() => route.query.preview === 'true')
  }
}

路由状态管理

javascript
// route-state.js
import { useRoute } from 'vue-router'
import { reactive, watch } from 'vue'

export function useRouteState() {
  const route = useRoute()
  
  const state = reactive({
    // 从路由初始化状态
    currentView: route.name,
    queryParams: { ...route.query },
    routeParams: { ...route.params },
    
    // 状态变更历史
    history: []
  })
  
  // 监听路由变化,更新状态
  watch(
    () => route.fullPath,
    (newPath, oldPath) => {
      state.currentView = route.name
      state.queryParams = { ...route.query }
      state.routeParams = { ...route.params }
      
      // 记录状态变更
      state.history.push({
        from: oldPath,
        to: newPath,
        timestamp: Date.now()
      })
    }
  )
  
  return state
}

最佳实践

1. 参数验证和默认值

javascript
function useSafeRouteParams() {
  const route = useRoute()
  
  return {
    // 带验证的用户ID
    userId: computed(() => {
      const id = parseInt(route.params.id)
      return id > 0 ? id : null
    }),
    
    // 带默认值的分页
    pagination: computed(() => ({
      page: Math.max(1, parseInt(route.query.page) || 1),
      limit: Math.min(50, parseInt(route.query.limit) || 10),
      sort: route.query.sort || 'created_at'
    })),
    
    // 安全的搜索词
    searchTerm: computed(() => {
      const term = route.query.q || ''
      return term.trim().slice(0, 100) // 限制长度
    })
  }
}

2. 性能优化

javascript
// 避免在模板中直接使用 route.params.id
// 不推荐:
<template>
  <div>{{ route.params.id }}</div>
</template>

// 推荐:
<script setup>
const route = useRoute()
const userId = computed(() => route.params.id)
</script>

<template>
  <div>{{ userId }}</div>
</template>

3. 类型安全(TypeScript)

typescript
import { useRoute } from 'vue-router'

// 定义路由参数类型
interface UserRouteParams {
  id: string
}

interface UserRouteQuery {
  tab?: string
  edit?: string
}

export function useUserRoute() {
  const route = useRoute()
  
  // 类型安全的参数访问
  const params = route.params as UserRouteParams
  const query = route.query as UserRouteQuery
  
  return {
    userId: params.id,
    activeTab: query.tab || 'profile',
    isEditMode: query.edit === 'true'
  }
}

注意事项

  1. 响应式依赖 - 在模板中使用路由属性时,确保使用计算属性或响应式引用
  2. 性能考虑 - 避免在渲染函数中频繁访问路由对象
  3. SSR 兼容 - 服务器端渲染时注意路由状态的同步
  4. 类型安全 - 使用 TypeScript 增强参数类型检查

兼容性

  • Vue 3.0+
  • 组合式 API
  • TypeScript 支持
  • SSR 兼容

🎯 总结useRoute 是访问当前路由信息的标准方式,它提供了响应式的路由数据访问。通过合理使用路由信息,可以构建出高度动态和交互性强的组件。

🚀 Vue Router - 让前端路由变得简单而强大 | 构建现代化单页应用的最佳选择