Skip to content

RouteLocationNormalized - 标准化路由位置接口

RouteLocationNormalized 接口定义了经过标准化处理的路由位置信息,它包含了路由匹配和解析后的完整数据,用于导航过程中的路由位置表示。📊

📋 接口定义

typescript
interface RouteLocationNormalized extends RouteLocationBase {
  // 继承 RouteLocationBase 的所有属性
  // 并确保这些属性已经过标准化处理
}

🎯 功能说明

这个接口表示路由位置已经完成了标准化处理,具有以下特点:

  1. 数据标准化 - 所有属性都经过统一格式处理
  2. 路径解析完成 - 动态参数和查询参数已正确解析
  3. 匹配信息完整 - 路由匹配记录已经生成
  4. 导航过程使用 - 主要用于导航守卫和路由解析过程

🔧 属性详解

继承了 RouteLocationBase 的所有属性,并确保这些属性都是标准化格式。

核心属性回顾

属性类型说明
pathstring标准化后的路径部分
paramsRouteParams解析后的路径参数对象
queryLocationQuery解析后的查询参数对象
hashstring标准化后的哈希部分
fullPathstring完整的标准化路径
matchedRouteRecordNormalized[]标准化后的匹配路由记录
metaRouteMeta合并后的路由元数据
redirectedFromRouteLocation | undefined标准化后的重定向来源

💡 实际应用示例

在导航守卫中使用

javascript
// 全局前置守卫
router.beforeEach((to, from) => {
  // to 和 from 都是 RouteLocationNormalized 类型
  console.log('从:', from.path, '导航到:', to.path)
  
  // 检查权限
  if (to.meta.requiresAuth && !isAuthenticated()) {
    // 重定向到登录页
    return '/login'
  }
  
  // 允许导航继续
  return true
})

路由解析守卫

javascript
// 全局解析守卫
router.beforeResolve(async (to, from) => {
  // 在所有组件内守卫和异步路由组件解析之后调用
  // to 此时已经是完整的标准化路由位置
  
  // 预加载数据
  if (to.meta.requiresData) {
    await preloadRouteData(to)
  }
  
  // 设置页面标题
  if (to.meta.title) {
    document.title = to.meta.title
  }
})

自定义路由处理逻辑

javascript
// 创建路由处理中间件
function createRouteMiddleware(handler) {
  return (to: RouteLocationNormalized, from: RouteLocationNormalized) => {
    // 在导航过程中处理路由信息
    return handler(to, from)
  }
}

// 使用示例:日志记录中间件
const loggingMiddleware = createRouteMiddleware((to, from) => {
  console.log(`路由变化: ${from.path} → ${to.path}`)
  console.log('参数:', to.params)
  console.log('查询:', to.query)
  return true
})

// 注册到路由守卫
router.beforeEach(loggingMiddleware)

🎯 与 RouteLocationNormalizedLoaded 的区别

使用时机不同

javascript
// RouteLocationNormalized - 导航过程中
router.beforeEach((to, from) => {
  // to 是 RouteLocationNormalized
  // 此时导航尚未完成,组件可能还未加载
})

// RouteLocationNormalizedLoaded - 导航完成后
const route = useRoute() // RouteLocationNormalizedLoaded
// 此时导航已完成,组件已加载

数据完整性

javascript
// 在导航守卫中(RouteLocationNormalized)
router.beforeEach((to, from) => {
  // to.matched 可能包含部分匹配信息
  // 异步组件可能还未解析完成
})

// 在组件中(RouteLocationNormalizedLoaded)
const route = useRoute()
// route.matched 包含完整的匹配信息
// 所有异步组件都已解析完成

🔧 实用工具函数

路由位置比较

typescript
// 比较两个路由位置是否相同(忽略哈希)
function areRoutesEqualIgnoringHash(
  a: RouteLocationNormalized,
  b: RouteLocationNormalized
): boolean {
  return a.path === b.path && 
         JSON.stringify(a.params) === JSON.stringify(b.params) &&
         JSON.stringify(a.query) === JSON.stringify(b.query)
}

// 检查是否是同一路由的不同参数
function isSameRouteWithDifferentParams(
  a: RouteLocationNormalized,
  b: RouteLocationNormalized
): boolean {
  return a.path === b.path && 
         a.name === b.name &&
         JSON.stringify(a.query) === JSON.stringify(b.query) &&
         // 只有参数不同
         JSON.stringify(a.params) !== JSON.stringify(b.params)
}

路由信息提取

typescript
// 提取路由的关键信息用于缓存或日志
function extractRouteKeyInfo(route: RouteLocationNormalized) {
  return {
    path: route.path,
    name: route.name,
    params: route.params,
    query: route.query,
    meta: route.meta
  }
}

// 创建路由的指纹(用于去重或比较)
function createRouteFingerprint(route: RouteLocationNormalized): string {
  return JSON.stringify({
    path: route.path,
    params: route.params,
    query: route.query
  })
}

路由转换工具

typescript
// 将路由位置转换为导航参数
function toNavigationParams(route: RouteLocationNormalized) {
  return {
    path: route.path,
    query: route.query,
    params: route.params,
    hash: route.hash
  }
}

// 从路由位置创建新的导航目标
function createRedirectTarget(
  route: RouteLocationNormalized,
  modifications: Partial<RouteLocationNormalized>
) {
  return {
    path: modifications.path || route.path,
    query: { ...route.query, ...modifications.query },
    params: { ...route.params, ...modifications.params },
    hash: modifications.hash || route.hash
  }
}

🎯 高级应用场景

动态权限控制系统

javascript
// 基于路由元数据的动态权限检查
async function checkRoutePermissions(
  to: RouteLocationNormalized
): Promise<boolean> {
  const requiredPermissions = to.meta.requiredPermissions || []
  
  if (requiredPermissions.length === 0) {
    return true // 无需权限
  }
  
  // 检查用户是否拥有所有所需权限
  const userPermissions = await getUserPermissions()
  return requiredPermissions.every(perm => 
    userPermissions.includes(perm)
  )
}

// 在导航守卫中使用
router.beforeEach(async (to, from) => {
  const hasPermission = await checkRoutePermissions(to)
  if (!hasPermission) {
    return '/unauthorized'
  }
  return true
})

A/B 测试路由系统

javascript
// 基于路由的 A/B 测试
function getVariantForRoute(route: RouteLocationNormalized): string {
  const routeKey = `${route.path}-${route.name || ''}`
  const variant = abTestManager.getVariant(routeKey)
  return variant || 'A' // 默认变体 A
}

// 在导航守卫中设置变体信息
router.beforeEach((to, from) => {
  const variant = getVariantForRoute(to)
  
  // 将变体信息添加到路由元数据
  to.meta.abTestVariant = variant
  
  // 根据变体决定是否重定向
  if (variant === 'B' && to.meta.hasVariantB) {
    return to.meta.variantBPath
  }
  
  return true
})

路由级数据预加载

javascript
// 路由数据预加载系统
const routeDataCache = new Map()

async function preloadRouteData(route: RouteLocationNormalized) {
  const cacheKey = route.fullPath
  
  // 检查缓存
  if (routeDataCache.has(cacheKey)) {
    return routeDataCache.get(cacheKey)
  }
  
  // 根据路由元数据决定预加载策略
  const preloadConfig = route.meta.preload || {}
  const data = await loadRequiredData(route, preloadConfig)
  
  // 缓存结果
  routeDataCache.set(cacheKey, data)
  return data
}

// 在解析守卫中使用
router.beforeResolve(async (to, from) => {
  if (to.meta.requiresData) {
    await preloadRouteData(to)
  }
})

🔗 相关接口

💡 专业建议:在导航守卫中处理 RouteLocationNormalized 时,注意异步操作的正确处理,确保返回适当的 Promise 或使用 async/await 语法。

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