Skip to content

RouteLocationNormalizedLoaded - 已加载的路由位置接口

RouteLocationNormalizedLoaded 接口扩展了基础路由位置,表示当前已激活且完成导航的路由位置。它包含了路由匹配完成后的完整信息。🚀

📋 接口定义

typescript
interface RouteLocationNormalizedLoaded extends RouteLocationBase {
  // 继承所有 RouteLocationBase 的属性
  // 并添加了特定于已加载路由的保证
}

🎯 功能说明

这个接口表示路由导航已经完成,具有以下特点:

  1. 导航完成 - 路由跳转已经成功执行
  2. 组件已加载 - 对应的路由组件已经准备就绪
  3. 数据可用 - 所有路由信息都是最新的和完整的
  4. 响应式保证 - 在 Vue 的响应式系统中正确工作

🔧 属性详解

继承了 RouteLocationBase 的所有属性,并确保这些属性在导航完成后都是可用的。

核心属性回顾

属性类型说明
pathstring当前路由的路径部分
paramsRouteParams路径参数对象
queryLocationQuery查询参数对象
hashstringURL 哈希部分
fullPathstring完整路径(包含所有部分)
matchedRouteRecordNormalized[]匹配的路由记录数组
metaRouteMeta路由元数据
redirectedFromRouteLocation | undefined重定向来源

💡 实际应用示例

在组件中访问当前路由

vue
<template>
  <div>
    <h1>当前页面: {{ route.meta.title || route.name }}</h1>
    <p>路径: {{ route.path }}</p>
    <p>参数: {{ JSON.stringify(route.params) }}</p>
    
    <!-- 显示匹配的路由层级 -->
    <div v-for="(record, index) in route.matched" :key="index">
      层级 {{ index }}: {{ record.path }}
    </div>
  </div>
</template>

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

// useRoute() 返回的就是 RouteLocationNormalizedLoaded
const route = useRoute()
</script>

基于路由参数的响应式逻辑

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

const route = useRoute()

// 计算属性基于路由参数
const userId = computed(() => route.params.id)
const isEditMode = computed(() => route.name === 'user-edit')

// 监听路由参数变化
watch(
  () => route.params.id,
  (newId, oldId) => {
    if (newId && newId !== oldId) {
      loadUserData(newId)
    }
  }
)

// 基于查询参数的逻辑
const searchQuery = computed(() => route.query.q || '')
const currentPage = computed(() => parseInt(route.query.page) || 1)
</script>

路由元数据的应用

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

const route = useRoute()

// 基于元数据的权限检查
const requiresAuth = computed(() => route.meta.requiresAuth === true)
const pageTitle = computed(() => route.meta.title || '默认标题')

// 合并所有匹配路由的元数据
const combinedMeta = computed(() => {
  return route.matched.reduce((meta, record) => ({
    ...meta,
    ...record.meta
  }), {})
})
</script>

🎯 高级用法

路由守卫中的数据预加载

javascript
router.beforeEach((to, from) => {
  // 在导航前预加载数据
  if (to.meta.requiresData) {
    return preloadRouteData(to).then(() => true)
  }
  return true
})

// 在组件中使用已加载的数据
const route = useRoute()
const preloadedData = computed(() => route.meta.preloadedData)

基于路由的组件渲染优化

vue
<template>
  <!-- 根据路由元数据动态渲染布局 -->
  <component 
    :is="layoutComponent" 
    v-if="route.matched.length > 0"
  >
    <router-view />
  </component>
</template>

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

const route = useRoute()

const layoutComponent = computed(() => {
  const layout = route.meta.layout || 'default'
  return defineAsyncComponent(() => import(`@/layouts/${layout}.vue`))
})
</script>

路由变化的历史追踪

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

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

// 记录路由变化历史
watch(
  () => route.fullPath,
  (newPath, oldPath) => {
    navigationHistory.value.push({
      from: oldPath,
      to: newPath,
      timestamp: Date.now(),
      params: route.params,
      query: route.query
    })
  },
  { immediate: true }
)

🔧 实用工具函数

路由信息快照

typescript
// 创建路由位置的不可变快照
function createRouteSnapshot(route: RouteLocationNormalizedLoaded) {
  return {
    path: route.path,
    fullPath: route.fullPath,
    params: { ...route.params },
    query: { ...route.query },
    hash: route.hash,
    meta: { ...route.meta },
    timestamp: Date.now()
  }
}

// 比较两个路由位置是否相同
function areRoutesEqual(
  a: RouteLocationNormalizedLoaded,
  b: RouteLocationNormalizedLoaded
): boolean {
  return a.fullPath === b.fullPath
}

路由参数验证和转换

typescript
// 安全的数字参数提取
function getValidatedParam(
  route: RouteLocationNormalizedLoaded,
  paramName: string,
  validator?: (value: any) => boolean
): any {
  const value = route.params[paramName]
  
  if (validator && !validator(value)) {
    throw new Error(`参数 ${paramName} 验证失败`)
  }
  
  return value
}

// 使用示例
const userId = getValidatedParam(route, 'id', (id) => /^\d+$/.test(id))

路由元数据工具

typescript
// 获取合并后的元数据
function getCombinedMeta(route: RouteLocationNormalizedLoaded) {
  return route.matched.reduce((meta, record) => ({
    ...meta,
    ...record.meta
  }), {})
}

// 检查特定元数据
function hasMeta(route: RouteLocationNormalizedLoaded, key: string): boolean {
  return getCombinedMeta(route)[key] !== undefined
}

// 获取特定元数据值
function getMetaValue(route: RouteLocationNormalizedLoaded, key: string): any {
  return getCombinedMeta(route)[key]
}

🚨 注意事项

导航过程中的状态

javascript
// 在导航过程中,路由信息可能不完整
router.beforeEach((to, from) => {
  // to 此时还不是 RouteLocationNormalizedLoaded
  // 它只是 RouteLocationNormalized
  console.log(to.matched) // 可能为空数组
})

// 导航完成后,在组件中访问的是完整的路由信息
const route = useRoute() // RouteLocationNormalizedLoaded
console.log(route.matched) // 完整的匹配记录

响应式依赖

javascript
// ✅ 正确:在计算属性或模板中使用
const userId = computed(() => route.params.id)

// ❌ 可能有问题:在异步回调中直接访问
setTimeout(() => {
  console.log(route.params.id) // 可能不是最新的
}, 1000)

🔗 相关接口

💡 专业建议:在组件中始终通过 useRoute() 获取当前路由信息,这样可以确保获得的是最新的、已加载完成的路由数据。

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