Official router for Vue.js 2 providing declarative routing, navigation guards, and nested route configuration.
—
Comprehensive guard system for controlling route transitions with global, per-route, and component-level hooks. Guards provide fine-grained control over navigation flow with support for authentication, authorization, and custom logic.
Router-wide navigation guards that apply to all route transitions.
/**
* Global before guard - runs before every route transition
* @param guard - Navigation guard function
* @returns Function to remove the guard
*/
beforeEach(guard: NavigationGuard): () => void;
/**
* Global before resolve guard - runs after all component guards and async components are resolved
* @param guard - Navigation guard function
* @returns Function to remove the guard
*/
beforeResolve(guard: NavigationGuard): () => void;
/**
* Global after hook - runs after every route transition (cannot affect navigation)
* @param hook - After navigation hook function
* @returns Function to remove the hook
*/
afterEach(hook: (to: Route, from: Route) => any): () => void;
/**
* Navigation guard function signature
* @param to - Target route being navigated to
* @param from - Current route being navigated away from
* @param next - Function to call to resolve the hook
*/
type NavigationGuard = (to: Route, from: Route, next: NavigationGuardNext) => any;
/**
* Next function for controlling navigation flow
* @param to - Optional navigation target or false to abort
*/
type NavigationGuardNext = (to?: RawLocation | false | ((vm: Vue) => any) | void) => void;Usage Examples:
// Authentication guard
const removeGuard = router.beforeEach((to, from, next) => {
if (to.meta.requiresAuth && !isAuthenticated()) {
next('/login');
} else {
next();
}
});
// Authorization guard
router.beforeEach((to, from, next) => {
if (to.meta.roles && !hasRequiredRole(to.meta.roles)) {
next('/unauthorized');
} else {
next();
}
});
// Loading state management
router.beforeEach((to, from, next) => {
showLoadingSpinner();
next();
});
router.afterEach((to, from) => {
hideLoadingSpinner();
// Analytics tracking
trackPageView(to.path);
// Update page title
document.title = to.meta.title || 'My App';
});
// Remove guard when no longer needed
removeGuard();Guards defined directly on route configurations.
/**
* Route-level guard in route configuration
*/
interface RouteConfig {
beforeEnter?: NavigationGuard;
}Usage Examples:
const routes = [
{
path: '/admin',
component: AdminPanel,
beforeEnter: (to, from, next) => {
if (!hasAdminAccess()) {
next('/dashboard');
} else {
next();
}
}
},
{
path: '/user/:id',
component: UserProfile,
beforeEnter: async (to, from, next) => {
try {
// Validate user exists and is accessible
await validateUserAccess(to.params.id);
next();
} catch (error) {
next('/not-found');
}
}
}
];Guards defined within Vue component definitions.
/**
* Component-level navigation guards (defined in component options)
*/
interface ComponentGuards {
/** Called when route is about to change but component is reused */
beforeRouteUpdate?: NavigationGuard;
/** Called before navigating away from this component */
beforeRouteLeave?: NavigationGuard;
/** Called when this route is confirmed (after all guards pass) */
beforeRouteEnter?: (to: Route, from: Route, next: (callback?: (vm: any) => any) => void) => any;
}Usage Examples:
// In component definition
export default {
name: 'UserProfile',
beforeRouteEnter(to, from, next) {
// Component instance not yet created, so no access to `this`
getUserData(to.params.id).then(user => {
next(vm => {
// Access component instance via callback
vm.setUser(user);
});
});
},
beforeRouteUpdate(to, from, next) {
// Component is reused, so `this` is available
this.loadUser(to.params.id);
next();
},
beforeRouteLeave(to, from, next) {
if (this.hasUnsavedChanges) {
const confirmed = confirm('You have unsaved changes. Are you sure you want to leave?');
if (confirmed) {
next();
} else {
next(false); // Cancel navigation
}
} else {
next();
}
}
};Guards for use with composition API (Vue 2.7+ or @vue/composition-api).
/**
* Composition API guard for route updates
* @param guard - Navigation guard to register
*/
function onBeforeRouteUpdate(guard: NavigationGuard): void;
/**
* Composition API guard for route leave
* @param guard - Navigation guard to register
*/
function onBeforeRouteLeave(guard: NavigationGuard): void;Usage Examples:
import { onBeforeRouteUpdate, onBeforeRouteLeave } from 'vue-router/composables';
export default {
setup() {
const hasUnsavedChanges = ref(false);
onBeforeRouteUpdate((to, from, next) => {
// Handle route parameter changes
if (to.params.id !== from.params.id) {
loadUserData(to.params.id);
}
next();
});
onBeforeRouteLeave((to, from, next) => {
if (hasUnsavedChanges.value) {
const confirmed = confirm('Leave without saving?');
next(confirmed);
} else {
next();
}
});
return {
hasUnsavedChanges
};
}
};Control navigation behavior using the next function.
/**
* Navigation control options for next() function
*/
type NavigationGuardNext = (
/** Continue navigation normally */
to?: void |
/** Abort current navigation */
false |
/** Redirect to different location */
RawLocation |
/** Execute callback when navigation confirmed (beforeRouteEnter only) */
((vm: Vue) => any)
) => void;Usage Examples:
router.beforeEach((to, from, next) => {
// Continue navigation
next();
// Abort navigation
next(false);
// Redirect to different route
next('/login');
next({ name: 'login', query: { redirect: to.fullPath }});
// Multiple conditions
if (!isAuthenticated()) {
next('/login');
} else if (!hasPermission(to.meta.permission)) {
next('/unauthorized');
} else {
next();
}
});
// Callback usage in beforeRouteEnter
beforeRouteEnter(to, from, next) {
fetchUserData(to.params.id).then(userData => {
next(vm => {
vm.userData = userData;
});
});
}Handle errors and failed navigation attempts.
/**
* Navigation error types
*/
enum NavigationFailureType {
aborted = 4,
cancelled = 8,
duplicated = 16,
redirected = 2
}
/**
* Check if error is a navigation failure
* @param error - Error to check
* @param type - Optional specific failure type to check for
* @returns True if error is navigation failure of specified type
*/
function isNavigationFailure(error: any, type?: NavigationFailureType): boolean;Usage Examples:
import { isNavigationFailure, NavigationFailureType } from 'vue-router';
// Handle navigation errors
router.push('/some-route').catch(error => {
if (isNavigationFailure(error, NavigationFailureType.aborted)) {
console.log('Navigation was aborted');
} else if (isNavigationFailure(error, NavigationFailureType.duplicated)) {
console.log('Navigation to same location');
} else {
console.error('Navigation error:', error);
}
});
// Global error handling
router.onError(error => {
console.error('Router error:', error);
// Handle errors globally
});
// Guard error handling
router.beforeEach(async (to, from, next) => {
try {
await validateRoute(to);
next();
} catch (error) {
console.error('Route validation failed:', error);
next('/error');
}
});Understanding the complete navigation resolution flow.
/**
* Complete navigation resolution flow:
* 1. Navigation triggered
* 2. Call beforeRouteLeave guards in deactivated components
* 3. Call global beforeEach guards
* 4. Call beforeRouteUpdate guards in reused components
* 5. Call beforeEnter in route configs
* 6. Resolve async route components
* 7. Call beforeRouteEnter in activated components
* 8. Call global beforeResolve guards
* 9. Navigation confirmed
* 10. Call global afterEach hooks
* 11. DOM updates triggered
* 12. Call callbacks passed to next in beforeRouteEnter guards
*/Usage Example:
// Complete guard setup demonstrating execution order
export default {
// Component guard (step 7)
beforeRouteEnter(to, from, next) {
console.log('7. beforeRouteEnter');
next();
},
// Component guard (step 4)
beforeRouteUpdate(to, from, next) {
console.log('4. beforeRouteUpdate');
next();
},
// Component guard (step 2)
beforeRouteLeave(to, from, next) {
console.log('2. beforeRouteLeave');
next();
}
};
// Route config guard (step 5)
const routes = [{
path: '/example',
component: ExampleComponent,
beforeEnter: (to, from, next) => {
console.log('5. beforeEnter');
next();
}
}];
// Global guards
router.beforeEach((to, from, next) => {
console.log('3. global beforeEach');
next();
});
router.beforeResolve((to, from, next) => {
console.log('8. global beforeResolve');
next();
});
router.afterEach((to, from) => {
console.log('10. global afterEach');
});interface NavigationFailure extends Error {
from: Route;
to: Route;
type: NavigationFailureType.aborted | NavigationFailureType.cancelled | NavigationFailureType.duplicated;
}
type ErrorHandler = (err: Error) => void;Install with Tessl CLI
npx tessl i tessl/npm-vue-router