routeLocationKey Variable | Vue Router
routeLocationKey is a symbol used as an injection key for providing and injecting the current route location in Vue components. It enables type-safe access to route information throughout your application. 🗺️
📋 Variable Definition
const routeLocationKey: InjectionKey<RouteLocationNormalizedLoaded> = Symbol()🎯 Purpose and Usage
The routeLocationKey variable provides a standardized way to inject the current route location into Vue components using Vue's dependency injection system. It gives you access to comprehensive route information with full type safety.
Key Benefits:
- ✅ Type Safety - Full TypeScript support for route data
- ✅ Reactive Access - Get reactive route information
- ✅ Dependency Injection - Clean component architecture
- ✅ Comprehensive Data - Access to all route properties
🔍 Technical Details
Injection Key Type
routeLocationKey is defined as an InjectionKey<RouteLocationNormalizedLoaded>, providing type information for the current route location.
Normalized Route Data
The injected value is a RouteLocationNormalizedLoaded object, which contains:
- Complete route information after normalization
- Reactive properties that update with route changes
- All route parameters, query, hash, and meta data
💡 Practical Usage Examples
Basic Route Location Injection
<script setup>
import { inject } from 'vue'
import { routeLocationKey } from 'vue-router'
// Inject current route location
const route = inject(routeLocationKey)
// Access route properties reactively
const currentPath = computed(() => route?.path)
const queryParams = computed(() => route?.query)
const routeParams = computed(() => route?.params)
</script>
<template>
<div>
<p>Current path: {{ currentPath }}</p>
<p>Query parameters: {{ queryParams }}</p>
<p>Route parameters: {{ routeParams }}</p>
</div>
</template>Route-Aware Component
<script setup>
import { inject, computed } from 'vue'
import { routeLocationKey } from 'vue-router'
interface Props {
activePaths?: string[]
}
const props = defineProps<Props>()
const route = inject(routeLocationKey)
// Check if current route matches active paths
const isActive = computed(() => {
if (!route || !props.activePaths) return false
return props.activePaths.some(path => route.path.startsWith(path))
})
// Get specific parameter with type safety
const userId = computed(() => {
return route?.params.id as string | undefined
})
// Watch for route changes
watch(() => route?.path, (newPath, oldPath) => {
console.log('Route changed:', oldPath, '→', newPath)
})
</script>
<template>
<div :class="{ active: isActive }">
<slot :route="route" :isActive="isActive" />
</div>
</template>Route-Based Service
import { inject } from 'vue'
import { routeLocationKey } from 'vue-router'
import type { RouteLocationNormalizedLoaded } from 'vue-router'
class RouteAnalyticsService {
private route: RouteLocationNormalizedLoaded | undefined
constructor() {
this.route = inject(routeLocationKey, undefined)
}
// Track page views based on route changes
trackPageView() {
if (!this.route) return
analytics.track('page_view', {
path: this.route.path,
query: this.route.query,
params: this.route.params,
timestamp: Date.now()
})
}
// Get route-specific configuration
getRouteConfig() {
if (!this.route) return null
return {
requiresAuth: this.route.meta.requiresAuth === true,
pageTitle: this.route.meta.title as string || 'Default Title',
breadcrumbs: this.route.meta.breadcrumbs as string[] || []
}
}
// Check if current route matches pattern
isRouteMatching(pattern: string | RegExp): boolean {
if (!this.route) return false
if (typeof pattern === 'string') {
return this.route.path === pattern
} else {
return pattern.test(this.route.path)
}
}
}🔧 Advanced Patterns
Type-Safe Route Injection Utility
import { inject } from 'vue'
import { routeLocationKey } from 'vue-router'
import type { RouteLocationNormalizedLoaded } from 'vue-router'
class RouteInjection {
// Safe route injection with validation
static injectRoute(): RouteLocationNormalizedLoaded {
const route = inject(routeLocationKey)
if (!route) {
throw new Error(
'Route location not found. ' +
'Make sure the component is within a router context.'
)
}
return route
}
// Optional route injection
static injectOptionalRoute(): RouteLocationNormalizedLoaded | undefined {
return inject(routeLocationKey, undefined)
}
// Route injection with custom fallback
static injectRouteWithFallback(fallback: Partial<RouteLocationNormalizedLoaded>) {
const route = inject(routeLocationKey, undefined)
return route ? route : { ...fallback } as RouteLocationNormalizedLoaded
}
}
// Usage examples
const route = RouteInjection.injectRoute() // Throws if not available
const optionalRoute = RouteInjection.injectOptionalRoute() // Undefined if not availableRoute-Based Composition Function
import { inject, computed, watch } from 'vue'
import { routeLocationKey } from 'vue-router'
import type { RouteLocationNormalizedLoaded } from 'vue-router'
export function useRouteInfo() {
const route = inject(routeLocationKey)
if (!route) {
throw new Error('useRouteInfo must be used within a router context')
}
// Computed properties for common route data
const currentPath = computed(() => route.path)
const queryParams = computed(() => route.query)
const routeParams = computed(() => route.params)
const routeMeta = computed(() => route.meta)
const routeHash = computed(() => route.hash)
// Route matching utilities
const isRouteActive = (path: string) => route.path === path
const isRouteStartingWith = (prefix: string) => route.path.startsWith(prefix)
const hasQueryParam = (key: string) => key in route.query
const hasRouteParam = (key: string) => key in route.params
// Watch for specific route changes
const watchRouteParam = (paramKey: string, callback: (value: string) => void) => {
watch(() => route.params[paramKey], (newValue, oldValue) => {
if (newValue !== oldValue) {
callback(newValue as string)
}
})
}
const watchQueryParam = (queryKey: string, callback: (value: string) => void) => {
watch(() => route.query[queryKey], (newValue, oldValue) => {
if (newValue !== oldValue) {
callback(newValue as string)
}
})
}
return {
route, // Full route object
currentPath,
queryParams,
routeParams,
routeMeta,
routeHash,
isRouteActive,
isRouteStartingWith,
hasQueryParam,
hasRouteParam,
watchRouteParam,
watchQueryParam
}
}
// Usage in component
const {
currentPath,
queryParams,
watchRouteParam
} = useRouteInfo()
watchRouteParam('id', (userId) => {
loadUserData(userId)
})Route-Based Permission System
import { inject } from 'vue'
import { routeLocationKey } from 'vue-router'
class RoutePermissionChecker {
private route: RouteLocationNormalizedLoaded | undefined
constructor() {
this.route = inject(routeLocationKey, undefined)
}
// Check if user can access current route
canAccess(currentUser: User): boolean {
if (!this.route) return true // Default to allowed if no route
// Check authentication requirement
if (this.route.meta.requiresAuth && !currentUser.isAuthenticated) {
return false
}
// Check role-based permissions
const requiredRoles = this.route.meta.requiredRoles as string[] | undefined
if (requiredRoles && requiredRoles.length > 0) {
const hasRequiredRole = requiredRoles.some(role =>
currentUser.roles.includes(role)
)
if (!hasRequiredRole) return false
}
// Check feature flags
const requiredFeatures = this.route.meta.requiredFeatures as string[] | undefined
if (requiredFeatures && requiredFeatures.length > 0) {
const hasFeatures = requiredFeatures.every(feature =>
currentUser.features.includes(feature)
)
if (!hasFeatures) return false
}
return true
}
// Get permission requirements for current route
getPermissionRequirements(): PermissionRequirements {
if (!this.route) return { requiresAuth: false }
return {
requiresAuth: this.route.meta.requiresAuth === true,
requiredRoles: this.route.meta.requiredRoles as string[] || [],
requiredFeatures: this.route.meta.requiredFeatures as string[] || []
}
}
}🚨 Important Considerations
Injection Context Requirements
// ✅ Correct: Using within component setup
<script setup>
import { inject } from 'vue'
import { routeLocationKey } from 'vue-router'
const route = inject(routeLocationKey) // Works in setup context
</script>
// ❌ Incorrect: Using outside component context
// This will not work - no injection context available
const route = inject(routeLocationKey) // undefined or errorReactivity and Performance
// The injected route is reactive
const route = inject(routeLocationKey)
// ✅ Good: Use computed properties for derived values
const userId = computed(() => route?.params.id as string)
// ❌ Avoid: Directly using route properties in templates
// This can cause unnecessary re-renders
<template>
<div>{{ route?.params.id }}</div> <!-- Potentially inefficient -->
</template>
// ✅ Better: Use computed properties
<template>
<div>{{ userId }}</div>
</template>🔗 Related APIs
routerKey- Injection key for router instancematchedRouteKey- Injection key for matched routeuseRoute()- Composition API for route access
📚 Best Practices
Safe Route Access Pattern
class SafeRouteAccess {
// Always validate route availability
static ensureRoute(route: RouteLocationNormalizedLoaded | undefined): RouteLocationNormalizedLoaded {
if (!route) {
throw new Error(
'Route location is not available. ' +
'Make sure your component is properly initialized.'
)
}
return route
}
// Safe parameter access with type checking
static getRouteParam(route: RouteLocationNormalizedLoaded | undefined, param: string): string | undefined {
const actualRoute = this.ensureRoute(route)
return actualRoute.params[param] as string | undefined
}
// Safe query parameter access
static getQueryParam(route: RouteLocationNormalizedLoaded | undefined, param: string): string | undefined {
const actualRoute = this.ensureRoute(route)
const value = actualRoute.query[param]
return Array.isArray(value) ? value[0] : value
}
}Route Injection Utility
// Create a reusable route injection utility
export function createRouteInjection<T extends Record<string, any>>(
customInjections?: T
) {
const route = inject(routeLocationKey)
if (!route) {
throw new Error('Route injection failed')
}
return {
route,
...customInjections
}
}
// Usage: Extend with custom functionality
const { route, customFeature } = createRouteInjection({
customFeature: () => { /* custom logic */ }
})💡 Pro Tip: Use
routeLocationKeyfor advanced route injection scenarios. For most components, prefer usinguseRoute()from Vue Router's composition API as it's simpler and more straightforward.