Skip to content

Router Interface | Vue Router

The Router interface represents the main router instance that manages navigation, route matching, and application routing state. This is the core object returned by createRouter() and used throughout your application. 🎯

📋 Interface Definition

typescript
interface Router {
  // Core properties
  readonly currentRoute: Ref<RouteLocationNormalizedLoaded>
  readonly options: RouterOptions
  
  // Navigation methods
  push(to: RouteLocationRaw): Promise<NavigationFailure | void | undefined>
  replace(to: RouteLocationRaw): Promise<NavigationFailure | void | undefined>
  go(delta: number): void
  back(): void
  forward(): void
  
  // Route management
  addRoute(parentName: string | symbol, route: RouteRecordRaw): () => void
  addRoute(route: RouteRecordRaw): () => void
  removeRoute(name: string | symbol): void
  hasRoute(name: string | symbol): boolean
  getRoutes(): RouteRecordNormalized[]
  resolve(to: RouteLocationRaw): RouteLocation & { href: string }
  
  // Event handling
  beforeEach(guard: NavigationGuard): () => void
  beforeResolve(guard: NavigationGuard): () => void
  afterEach(guard: NavigationHookAfter): () => void
  onError(handler: (error: any) => void): () => void
  
  // Installation
  install(app: App): void
}

🎯 Core Properties

currentRoute - Current Route Reference

A reactive reference to the currently active route. This property is updated automatically whenever navigation occurs.

typescript
const router: Router
const currentRoute = router.currentRoute // Ref<RouteLocationNormalizedLoaded>

// Access reactive route information
console.log(currentRoute.value.path)     // Current path
console.log(currentRoute.value.params)  // Route parameters
console.log(currentRoute.value.query)   // Query parameters

options - Router Configuration

The original configuration options passed to createRouter(). This is read-only and contains the router's initial setup.

typescript
const router: Router
console.log(router.options.history)    // History implementation
console.log(router.options.routes)     // Route definitions
console.log(router.options.scrollBehavior) // Scroll behavior config

🧭 Navigation Methods

push() - Navigate to New Location

Programmatically navigates to a new route, adding an entry to the browser's history stack.

typescript
// Various usage patterns
await router.push('/home')                          // String path
await router.push({ path: '/user/123' })           // Location object
await router.push({ name: 'user', params: { id: 123 } }) // Named route
await router.push({ path: '/search', query: { q: 'vue' } }) // With query

// Error handling
try {
  await router.push('/protected-route')
} catch (error) {
  if (isNavigationFailure(error)) {
    console.log('Navigation was blocked')
  }
}

replace() - Replace Current Location

Navigates to a new route without adding a new entry to the history stack (replaces current entry).

typescript
// Useful for redirects or login flows
await router.replace('/new-location')
await router.replace({ name: 'redirect-target' })

// Example: redirect after login
async function handleLogin() {
  await loginUser(credentials)
  router.replace('/dashboard') // Replace login page in history
}

History Navigation Methods

Control browser history navigation programmatically.

typescript
router.back()      // Go back one step (equivalent to browser back button)
router.forward()   // Go forward one step
router.go(1)       // Go forward 1 step
router.go(-2)      // Go back 2 steps
router.go(0)       // Reload current page (if supported by history implementation)

🛣️ Route Management

Dynamic Route Addition

Add routes dynamically after router initialization.

typescript
// Add a single route
const removeRoute = router.addRoute({
  path: '/dynamic',
  component: DynamicComponent
})

// Add nested route under parent
router.addRoute('admin', {
  path: 'settings',
  component: AdminSettings
})

// Remove route later
removeRoute() // Or use router.removeRoute('route-name')

Route Inspection and Resolution

Check route existence and resolve route locations.

typescript
// Check if route exists
if (router.hasRoute('user-profile')) {
  console.log('User profile route is available')
}

// Get all registered routes
const allRoutes = router.getRoutes()
allRoutes.forEach(route => {
  console.log(route.path, route.name)
})

// Resolve a route location to get full URL
const resolved = router.resolve({ name: 'product', params: { id: 456 } })
console.log(resolved.href) // Full URL including base

🛡️ Navigation Guards

Add guards that run for every navigation.

typescript
// Global beforeEach guard
const removeGuard = router.beforeEach((to, from) => {
  if (to.meta.requiresAuth && !isAuthenticated()) {
    return '/login' // Redirect to login
  }
})

// Global afterEach guard (no return value)
router.afterEach((to, from, failure) => {
  if (failure) {
    console.log('Navigation failed:', failure)
  } else {
    console.log('Navigation succeeded to:', to.path)
  }
})

// Remove guard when no longer needed
removeGuard()

Error Handling

Handle navigation errors globally.

typescript
router.onError((error) => {
  console.error('Router error occurred:', error)
  
  if (error.code === 'CHUNK_LOAD_ERROR') {
    // Handle lazy loading errors
    showChunkErrorModal()
  }
})

💡 Practical Examples

Programmatic Navigation Flow

typescript
class NavigationService {
  constructor(private router: Router) {}
  
  async navigateToUserProfile(userId: string) {
    try {
      await this.router.push({
        name: 'user-profile',
        params: { id: userId }
      })
      console.log('Navigation to user profile completed')
    } catch (error) {
      if (isNavigationFailure(error, NavigationFailureType.aborted)) {
        console.log('Navigation was aborted by a guard')
        this.showAccessDeniedMessage()
      } else {
        console.error('Unexpected navigation error:', error)
        this.showErrorMessage()
      }
    }
  }
  
  async redirectToLogin(returnUrl?: string) {
    await this.router.replace({
      path: '/login',
      query: returnUrl ? { return: returnUrl } : undefined
    })
  }
}

Dynamic Route Management

typescript
class FeatureManager {
  constructor(private router: Router) {
    this.registeredFeatures = new Set()
  }
  
  enableFeature(featureName: string, featureRoute: RouteRecordRaw) {
    if (this.router.hasRoute(featureName)) {
      console.warn(`Feature ${featureName} is already enabled`)
      return
    }
    
    // Add feature route dynamically
    this.router.addRoute(featureRoute)
    this.registeredFeatures.add(featureName)
    
    console.log(`Feature ${featureName} enabled`)
  }
  
  disableFeature(featureName: string) {
    if (this.router.hasRoute(featureName)) {
      this.router.removeRoute(featureName)
      this.registeredFeatures.delete(featureName)
      console.log(`Feature ${featureName} disabled`)
    }
  }
  
  isFeatureEnabled(featureName: string): boolean {
    return this.router.hasRoute(featureName)
  }
}

Advanced Guard Management

typescript
class AuthGuardManager {
  private authGuard: (() => void) | null = null
  
  setupAuthGuard(router: Router) {
    // Remove existing guard if any
    this.teardownAuthGuard()
    
    // Setup new auth guard
    this.authGuard = router.beforeEach((to, from) => {
      if (to.meta.requiresAuth) {
        if (!this.isAuthenticated()) {
          // Redirect to login with return URL
          return {
            path: '/login',
            query: { redirect: to.fullPath }
          }
        }
        
        if (to.meta.requiredRole && !this.hasRole(to.meta.requiredRole)) {
          // User doesn't have required role
          return { path: '/access-denied' }
        }
      }
    })
  }
  
  teardownAuthGuard() {
    if (this.authGuard) {
      this.authGuard()
      this.authGuard = null
    }
  }
}

🚨 Important Notes

Reactivity Considerations

typescript
const router = useRouter()

// ✅ Correct - access current route reactively
const currentPath = computed(() => router.currentRoute.value.path)

// ❌ Incorrect - losing reactivity
const currentPath = router.currentRoute.value.path // Not reactive!

// ✅ Correct - watch for route changes
watch(() => router.currentRoute.value.path, (newPath) => {
  console.log('Path changed to:', newPath)
})

Error Handling Best Practices

typescript
// Always handle navigation errors
router.push('/target').catch(error => {
  if (isNavigationFailure(error)) {
    // Handle specific navigation failures
    handleNavigationError(error)
  } else {
    // Handle other types of errors
    console.error('Unexpected error:', error)
  }
})

// Or use async/await with try-catch
try {
  await router.push('/target')
} catch (error) {
  handleNavigationError(error)
}

💡 Pro Tip: Use the resolve() method when you need to generate URLs for external use or when working with external navigation systems.

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