RouteLocationNormalizedLoaded - 已加载的路由位置接口
RouteLocationNormalizedLoaded 接口扩展了基础路由位置,表示当前已激活且完成导航的路由位置。它包含了路由匹配完成后的完整信息。🚀
📋 接口定义
typescript
interface RouteLocationNormalizedLoaded extends RouteLocationBase {
// 继承所有 RouteLocationBase 的属性
// 并添加了特定于已加载路由的保证
}🎯 功能说明
这个接口表示路由导航已经完成,具有以下特点:
- 导航完成 - 路由跳转已经成功执行
- 组件已加载 - 对应的路由组件已经准备就绪
- 数据可用 - 所有路由信息都是最新的和完整的
- 响应式保证 - 在 Vue 的响应式系统中正确工作
🔧 属性详解
继承了 RouteLocationBase 的所有属性,并确保这些属性在导航完成后都是可用的。
核心属性回顾
| 属性 | 类型 | 说明 |
|---|---|---|
path | string | 当前路由的路径部分 |
params | RouteParams | 路径参数对象 |
query | LocationQuery | 查询参数对象 |
hash | string | URL 哈希部分 |
fullPath | string | 完整路径(包含所有部分) |
matched | RouteRecordNormalized[] | 匹配的路由记录数组 |
meta | RouteMeta | 路由元数据 |
redirectedFrom | RouteLocation | 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)🔗 相关接口
RouteLocationBase- 基础路由位置接口RouteLocationNormalized- 标准化路由位置RouteRecordNormalized- 标准化路由记录
💡 专业建议:在组件中始终通过
useRoute()获取当前路由信息,这样可以确保获得的是最新的、已加载完成的路由数据。