matchedRouteKey Variable | Vue Router
matchedRouteKey is a symbol used as an injection key for providing and injecting the currently matched route record in Vue components. It gives you access to the route configuration that matches the current URL. 🎯
📋 Variable Definition
const matchedRouteKey: InjectionKey<RouteRecordNormalized> = Symbol()🎯 Purpose and Usage
The matchedRouteKey variable provides a standardized way to inject the matched route record into Vue components using Vue's dependency injection system. This gives you access to the route configuration that was used to match the current URL.
Key Benefits:
- ✅ Route Configuration Access - Get the route record that matched
- ✅ Meta Information - Access route meta data and configuration
- ✅ Component Information - See which components are associated
- ✅ Type Safety - Full TypeScript support for route records
🔍 Technical Details
Injection Key Type
matchedRouteKey is defined as an InjectionKey<RouteRecordNormalized>, providing type information for the matched route record.
Route Record Information
The injected value is a RouteRecordNormalized object, which contains:
- Complete route configuration
- Component mappings
- Route meta information
- Children routes and aliases
💡 Practical Usage Examples
Basic Matched Route Injection
<script setup>
import { inject } from 'vue'
import { matchedRouteKey } from 'vue-router'
// Inject matched route record
const matchedRoute = inject(matchedRouteKey)
// Access route configuration
const routeName = computed(() => matchedRoute?.name)
const routePath = computed(() => matchedRoute?.path)
const routeMeta = computed(() => matchedRoute?.meta)
const routeComponents = computed(() => matchedRoute?.components)
</script>
<template>
<div v-if="matchedRoute">
<h3>Matched Route Information</h3>
<p>Name: {{ routeName }}</p>
<p>Path: {{ routePath }}</p>
<p>Meta: {{ routeMeta }}</p>
</div>
</template>Route Configuration Component
<script setup>
import { inject, computed } from 'vue'
import { matchedRouteKey } from 'vue-router'
interface Props {
showDetails?: boolean
}
const props = defineProps<Props>()
const matchedRoute = inject(matchedRouteKey)
// Extract useful information from matched route
const routeInfo = computed(() => {
if (!matchedRoute) return null
return {
name: matchedRoute.name,
path: matchedRoute.path,
hasChildren: matchedRoute.children.length > 0,
childCount: matchedRoute.children.length,
hasAliases: matchedRoute.alias.length > 0,
metaKeys: Object.keys(matchedRoute.meta),
componentNames: Object.keys(matchedRoute.components)
}
})
// Check if route has specific meta property
const hasMetaProperty = (key: string) => {
return matchedRoute ? key in matchedRoute.meta : false
}
// Get specific meta value with type safety
const getMetaValue = <T>(key: string, defaultValue: T): T => {
if (!matchedRoute || !(key in matchedRoute.meta)) {
return defaultValue
}
return matchedRoute.meta[key] as T
}
</script>
<template>
<div v-if="routeInfo && props.showDetails" class="route-info">
<h4>Route Configuration</h4>
<ul>
<li>Name: {{ routeInfo.name }}</li>
<li>Path: {{ routeInfo.path }}</li>
<li>Children: {{ routeInfo.childCount }}</li>
<li>Components: {{ routeInfo.componentNames.join(', ') }}</li>
</ul>
</div>
</template>Route-Based Feature Detection
import { inject } from 'vue'
import { matchedRouteKey } from 'vue-router'
import type { RouteRecordNormalized } from 'vue-router'
class RouteFeatureDetector {
private matchedRoute: RouteRecordNormalized | undefined
constructor() {
this.matchedRoute = inject(matchedRouteKey, undefined)
}
// Check if current route has specific feature
hasFeature(feature: string): boolean {
if (!this.matchedRoute) return false
const features = this.matchedRoute.meta.features as string[] | undefined
return features ? features.includes(feature) : false
}
// Get all features for current route
getFeatures(): string[] {
if (!this.matchedRoute) return []
const features = this.matchedRoute.meta.features as string[] | undefined
return features || []
}
// Check if route requires specific permission
requiresPermission(permission: string): boolean {
if (!this.matchedRoute) return false
const permissions = this.matchedRoute.meta.permissions as string[] | undefined
return permissions ? permissions.includes(permission) : false
}
// Get route-specific configuration
getRouteConfig(): RouteConfig {
if (!this.matchedRoute) return {}
return {
layout: this.matchedRoute.meta.layout as string || 'default',
requiresAuth: this.matchedRoute.meta.requiresAuth === true,
pageTitle: this.matchedRoute.meta.title as string || '',
breadcrumbs: this.matchedRoute.meta.breadcrumbs as string[] || []
}
}
}🔧 Advanced Patterns
Type-Safe Matched Route Injection
import { inject } from 'vue'
import { matchedRouteKey } from 'vue-router'
import type { RouteRecordNormalized } from 'vue-router'
class MatchedRouteInjection {
// Safe injection with validation
static injectMatchedRoute(): RouteRecordNormalized {
const matchedRoute = inject(matchedRouteKey)
if (!matchedRoute) {
throw new Error(
'Matched route not found. ' +
'Make sure the component is within a router context.'
)
}
return matchedRoute
}
// Optional injection
static injectOptionalMatchedRoute(): RouteRecordNormalized | undefined {
return inject(matchedRouteKey, undefined)
}
// Injection with fallback configuration
static injectMatchedRouteWithFallback(fallback: Partial<RouteRecordNormalized>) {
const matchedRoute = inject(matchedRouteKey, undefined)
return matchedRoute ? matchedRoute : { ...fallback } as RouteRecordNormalized
}
}
// Usage examples
const matchedRoute = MatchedRouteInjection.injectMatchedRoute()
const optionalRoute = MatchedRouteInjection.injectOptionalMatchedRoute()Matched Route Composition Function
import { inject, computed } from 'vue'
import { matchedRouteKey } from 'vue-router'
import type { RouteRecordNormalized } from 'vue-router'
export function useMatchedRoute() {
const matchedRoute = inject(matchedRouteKey)
if (!matchedRoute) {
throw new Error('useMatchedRoute must be used within a router context')
}
// Computed properties for common route record data
const routeName = computed(() => matchedRoute.name)
const routePath = computed(() => matchedRoute.path)
const routeMeta = computed(() => matchedRoute.meta)
const routeComponents = computed(() => matchedRoute.components)
const routeChildren = computed(() => matchedRoute.children)
const routeAliases = computed(() => matchedRoute.alias)
// Route record analysis
const routeAnalysis = computed(() => ({
hasChildren: matchedRoute.children.length > 0,
childCount: matchedRoute.children.length,
hasAliases: matchedRoute.alias.length > 0,
aliasCount: matchedRoute.alias.length,
componentCount: Object.keys(matchedRoute.components).length,
metaKeyCount: Object.keys(matchedRoute.meta).length
}))
// Meta data utilities
const getMetaValue = <T>(key: string, defaultValue: T): T => {
return (matchedRoute.meta[key] as T) || defaultValue
}
const hasMetaKey = (key: string): boolean => {
return key in matchedRoute.meta
}
// Component utilities
const getComponent = (name: string = 'default') => {
return matchedRoute.components[name]
}
const hasComponent = (name: string = 'default'): boolean => {
return name in matchedRoute.components
}
return {
matchedRoute, // Full matched route object
routeName,
routePath,
routeMeta,
routeComponents,
routeChildren,
routeAliases,
routeAnalysis,
getMetaValue,
hasMetaKey,
getComponent,
hasComponent
}
}
// Usage in component
const {
routeMeta,
getMetaValue,
routeAnalysis
} = useMatchedRoute()
const pageTitle = getMetaValue('title', 'Default Title')
const requiresAuth = getMetaValue('requiresAuth', false)Dynamic Layout System Based on Matched Route
import { inject } from 'vue'
import { matchedRouteKey } from 'vue-router'
class DynamicLayoutSystem {
private matchedRoute: RouteRecordNormalized | undefined
constructor() {
this.matchedRoute = inject(matchedRouteKey, undefined)
}
// Get layout component based on route meta
getLayoutComponent(): Component {
if (!this.matchedRoute) {
return DefaultLayout
}
const layoutName = this.matchedRoute.meta.layout as string || 'default'
switch (layoutName) {
case 'admin':
return AdminLayout
case 'auth':
return AuthLayout
case 'empty':
return EmptyLayout
default:
return DefaultLayout
}
}
// Check if route should use specific layout
shouldUseLayout(layout: string): boolean {
if (!this.matchedRoute) return layout === 'default'
const routeLayout = this.matchedRoute.meta.layout as string || 'default'
return routeLayout === layout
}
// Get layout configuration
getLayoutConfig(): LayoutConfig {
if (!this.matchedRoute) return {}
return {
showHeader: this.matchedRoute.meta.showHeader !== false,
showFooter: this.matchedRoute.meta.showFooter !== false,
showSidebar: this.matchedRoute.meta.showSidebar === true,
sidebarCollapsed: this.matchedRoute.meta.sidebarCollapsed === true
}
}
}🚨 Important Considerations
Injection Context Requirements
// ✅ Correct: Using within component setup
<script setup>
import { inject } from 'vue'
import { matchedRouteKey } from 'vue-router'
const matchedRoute = inject(matchedRouteKey) // Works in setup context
</script>
// ❌ Incorrect: Using outside component context
// This will not work - no injection context available
const matchedRoute = inject(matchedRouteKey) // undefined or errorMatched Route vs Current Route
// Important distinction:
// - matchedRouteKey: Provides the route record that matched the URL
// - routeLocationKey: Provides the current route location information
// They contain different but complementary information:
// matchedRoute: Configuration (meta, components, path pattern)
// routeLocation: Current state (params, query, actual path)🔗 Related APIs
routerKey- Injection key for router instancerouteLocationKey- Injection key for current route location
📚 Best Practices
Safe Matched Route Access
class SafeMatchedRouteAccess {
// Always validate matched route availability
static ensureMatchedRoute(matchedRoute: RouteRecordNormalized | undefined): RouteRecordNormalized {
if (!matchedRoute) {
throw new Error(
'Matched route is not available. ' +
'Make sure your component is properly initialized.'
)
}
return matchedRoute
}
// Safe meta data access
static getMetaValue<T>(
matchedRoute: RouteRecordNormalized | undefined,
key: string,
defaultValue: T
): T {
const actualRoute = this.ensureMatchedRoute(matchedRoute)
return (actualRoute.meta[key] as T) || defaultValue
}
}Matched Route Injection Utility
// Create a reusable matched route injection utility
export function createMatchedRouteInjection<T extends Record<string, any>>(
customInjections?: T
) {
const matchedRoute = inject(matchedRouteKey)
if (!matchedRoute) {
throw new Error('Matched route injection failed')
}
return {
matchedRoute,
...customInjections
}
}
// Usage: Extend with custom functionality
const { matchedRoute, customFeature } = createMatchedRouteInjection({
customFeature: () => { /* custom logic */ }
})💡 Pro Tip: Use
matchedRouteKeywhen you need access to the route configuration that matched the current URL. This is particularly useful for dynamic layout systems, permission checks, and feature flags based on route configuration.