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 - 让前端路由变得简单而强大 | 构建现代化单页应用的最佳选择