routerKey Variable | Vue Router
routerKey is a symbol used as an injection key for providing and injecting the router instance in Vue components. It enables type-safe access to the router instance throughout your application. 🔑
📋 Variable Definition
const routerKey: InjectionKey<Router> = Symbol()🎯 Purpose and Usage
The routerKey variable provides a standardized way to inject the router instance into Vue components using Vue's dependency injection system. It ensures type safety and prevents naming conflicts.
Key Benefits:
- ✅ Type Safety - Ensures proper typing for injected router
- ✅ Dependency Injection - Enables clean component architecture
- ✅ Framework Integration - Works seamlessly with Vue's injection system
- ✅ Avoids Magic Strings - Uses symbols instead of string keys
🔍 Technical Details
Injection Key Type
routerKey is defined as an InjectionKey<Router>, which is a Vue-specific type that provides type information for dependency injection.
Symbol-Based Identification
As a symbol, routerKey is guaranteed to be unique, preventing conflicts with other injection keys in your application.
💡 Practical Usage Examples
Basic Router Injection
<script setup>
import { inject } from 'vue'
import { routerKey } from 'vue-router'
// Inject router instance using the key
const router = inject(routerKey)
// Use the router instance
function navigateToHome() {
router?.push('/')
}
</script>Custom Component with Router Access
<script setup>
import { inject } from 'vue'
import { routerKey } from 'vue-router'
interface Props {
to: string | RouteLocationRaw
}
const props = defineProps<Props>()
const router = inject(routerKey)
const navigate = () => {
if (!router) {
console.warn('Router not available')
return
}
if (typeof props.to === 'string') {
router.push(props.to)
} else {
router.push(props.to)
}
}
</script>
<template>
<button @click="navigate">
<slot>Navigate</slot>
</button>
</template>Router-Aware Service
import { inject } from 'vue'
import { routerKey } from 'vue-router'
import type { Router } from 'vue-router'
class NavigationService {
private router: Router | undefined
constructor() {
// Inject router in constructor or initialize later
this.router = inject(routerKey, undefined)
}
initialize(router: Router) {
this.router = router
}
navigateTo(path: string, query?: Record<string, string>) {
if (!this.router) {
throw new Error('Router not initialized')
}
this.router.push({
path,
query
})
}
// Static method for quick navigation
static navigate(path: string) {
const router = inject(routerKey)
router?.push(path)
}
}
// Usage in component
const navigationService = new NavigationService()
</script>🔧 Advanced Patterns
Type-Safe Router Injection Utility
import { inject, type InjectionKey } from 'vue'
import { routerKey } from 'vue-router'
import type { Router } from 'vue-router'
class RouterInjection {
// Safe router injection with fallback
static injectRouter(): Router {
const router = inject(routerKey)
if (!router) {
throw new Error(
'Router instance not found. ' +
'Make sure the component is wrapped in a router provider.'
)
}
return router
}
// Optional router injection
static injectOptionalRouter(): Router | undefined {
return inject(routerKey, undefined)
}
// Router injection with custom error message
static injectRouterWithMessage(errorMessage: string): Router {
const router = inject(routerKey)
if (!router) {
throw new Error(errorMessage)
}
return router
}
}
// Usage examples
const router = RouterInjection.injectRouter() // Throws if not available
const optionalRouter = RouterInjection.injectOptionalRouter() // Undefined if not availableRouter-Aware Composition Function
import { inject } from 'vue'
import { routerKey } from 'vue-router'
import type { Router } from 'vue-router'
export function useRouterNavigation() {
const router = inject(routerKey)
if (!router) {
throw new Error('useRouterNavigation must be used within a router context')
}
const navigate = (to: string | RouteLocationRaw) => {
if (typeof to === 'string') {
router.push(to)
} else {
router.push(to)
}
}
const replace = (to: string | RouteLocationRaw) => {
if (typeof to === 'string') {
router.replace(to)
} else {
router.replace(to)
}
}
const go = (delta: number) => {
router.go(delta)
}
const back = () => {
router.back()
}
const forward = () => {
router.forward()
}
return {
navigate,
replace,
go,
back,
forward,
router // Expose the full router instance
}
}
// Usage in component
const { navigate, back } = useRouterNavigation()Testing with Mock Router
import { routerKey } from 'vue-router'
import { createApp } from 'vue'
// Mock router for testing
const mockRouter = {
push: vi.fn(),
replace: vi.fn(),
go: vi.fn(),
back: vi.fn(),
forward: vi.fn()
}
// Test setup helper
function setupTestWithRouter(component: any) {
const app = createApp(component)
app.provide(routerKey, mockRouter)
return { app, mockRouter }
}
// Component test example
describe('RouterAwareComponent', () => {
it('should navigate when button clicked', async () => {
const { app, mockRouter } = setupTestWithRouter(TestComponent)
const wrapper = mount(app)
await wrapper.find('button').trigger('click')
expect(mockRouter.push).toHaveBeenCalledWith('/target')
})
})🚨 Important Considerations
Injection Context Requirements
// ✅ Correct: Using within component setup
<script setup>
import { inject } from 'vue'
import { routerKey } from 'vue-router'
const router = inject(routerKey) // Works in setup context
</script>
// ❌ Incorrect: Using outside component context
// This will not work - no injection context available
const router = inject(routerKey) // undefined or errorProvider Setup
// The router must be provided at the app level
import { createApp } from 'vue'
import { createRouter, routerKey } from 'vue-router'
const router = createRouter({ /* config */ })
const app = createApp(App)
// Router is automatically provided by Vue Router
// But you can also provide it manually if needed
app.provide(routerKey, router)🔗 Related APIs
routeLocationKey- Injection key for current route locationmatchedRouteKey- Injection key for matched route- Vue Dependency Injection - Vue's provide/inject system
📚 Best Practices
Safe Router Access Pattern
class SafeRouterAccess {
// Always check if router is available
static ensureRouter(router: Router | undefined): Router {
if (!router) {
throw new Error(
'Router instance is not available. ' +
'Make sure your component is properly initialized.'
)
}
return router
}
// Graceful navigation with error handling
static async safeNavigate(
router: Router | undefined,
to: RouteLocationRaw
): Promise<boolean> {
try {
const actualRouter = this.ensureRouter(router)
await actualRouter.push(to)
return true
} catch (error) {
console.error('Navigation failed:', error)
return false
}
}
}Router Injection Utility
// Create a reusable router injection utility
export function createRouterInjection<T extends Record<string, any>>(
customInjections?: T
) {
const router = inject(routerKey)
if (!router) {
throw new Error('Router injection failed')
}
return {
router,
...customInjections
}
}
// Usage: Extend with custom functionality
const { router, customFeature } = createRouterInjection({
customFeature: () => { /* custom logic */ }
})💡 Pro Tip: Use
routerKeyfor type-safe router injection in custom components and services. For most components, prefer usinguseRouter()from Vue Router's composition API as it's simpler and more straightforward.