Official router for Vue.js 2 providing declarative routing, navigation guards, and nested route configuration.
—
Vue 3-style composables for accessing router functionality in composition API components. These functions provide reactive access to router state and navigation controls for use with Vue 2.7+ composition API or @vue/composition-api plugin.
import { useRouter, useRoute, onBeforeRouteUpdate, onBeforeRouteLeave, useLink } from 'vue-router/composables';Access router instance and current route reactively.
/**
* Access the router instance
* @returns VueRouter instance
*/
function useRouter(): VueRouter;
/**
* Access the current route (reactive)
* @returns Reactive route object that updates when route changes
*/
function useRoute(): Route;Usage Examples:
import { useRouter, useRoute } from 'vue-router/composables';
import { computed, watch } from 'vue';
export default {
setup() {
const router = useRouter();
const route = useRoute();
// Reactive route properties
const userId = computed(() => route.params.id);
const currentPath = computed(() => route.path);
const queryParams = computed(() => route.query);
// Watch route changes
watch(() => route.params.id, (newId, oldId) => {
console.log(`User changed from ${oldId} to ${newId}`);
loadUserData(newId);
});
// Navigation methods
const navigateToUser = (id) => {
router.push({ name: 'user', params: { id }});
};
const goBack = () => {
router.go(-1);
};
return {
userId,
currentPath,
queryParams,
navigateToUser,
goBack
};
}
};Register navigation guards that are automatically cleaned up when component is unmounted.
/**
* Register guard for route updates (when component is reused)
* @param guard - Navigation guard function
*/
function onBeforeRouteUpdate(guard: NavigationGuard): void;
/**
* Register guard for leaving current route
* @param guard - Navigation guard function
*/
function onBeforeRouteLeave(guard: NavigationGuard): void;Usage Examples:
import { onBeforeRouteUpdate, onBeforeRouteLeave } from 'vue-router/composables';
import { ref, onMounted } from 'vue';
export default {
setup() {
const userData = ref(null);
const hasUnsavedChanges = ref(false);
const loading = ref(false);
// Handle route parameter changes
onBeforeRouteUpdate(async (to, from, next) => {
if (to.params.id !== from.params.id) {
loading.value = true;
try {
userData.value = await fetchUser(to.params.id);
next();
} catch (error) {
console.error('Failed to load user:', error);
next(false); // Cancel navigation
} finally {
loading.value = false;
}
} else {
next();
}
});
// Prevent leaving with unsaved changes
onBeforeRouteLeave((to, from, next) => {
if (hasUnsavedChanges.value) {
const confirmed = window.confirm(
'You have unsaved changes. Are you sure you want to leave?'
);
next(confirmed);
} else {
next();
}
});
const saveChanges = async () => {
// Save logic
hasUnsavedChanges.value = false;
};
return {
userData,
hasUnsavedChanges,
loading,
saveChanges
};
}
};Access RouterLink functionality programmatically with reactive state.
/**
* RouterLink composable options
*/
interface RouterLinkOptions {
/** Route location to link to */
to: Route | Ref<Route>;
/** Use replace instead of push */
replace?: boolean;
}
/**
* RouterLink functionality as composable
* @param options - Link configuration
* @returns Reactive link state and navigation function
*/
function useLink(options: RouterLinkOptions): {
/** Computed route object */
route: ComputedRef<Route>;
/** Whether link is active */
isActive: ComputedRef<boolean>;
/** Whether link is exact active */
isExactActive: ComputedRef<boolean>;
/** Resolved href */
href: ComputedRef<string>;
/** Navigation function */
navigate: () => Promise<void>;
};Usage Examples:
import { useLink } from 'vue-router/composables';
import { ref, computed } from 'vue';
export default {
setup() {
const selectedUser = ref('123');
// Dynamic link based on reactive data
const userLink = useLink({
to: computed(() => ({
name: 'user',
params: { id: selectedUser.value }
}))
});
// Custom navigation with confirmation
const handleNavigation = async () => {
const confirmed = await showConfirmDialog('Navigate to user?');
if (confirmed) {
userLink.navigate();
}
};
// Multiple links
const links = computed(() => [
useLink({ to: { name: 'home' }}),
useLink({ to: { name: 'about' }}),
useLink({ to: { name: 'contact' }})
]);
return {
selectedUser,
userLink,
handleNavigation,
links
};
}
};Extract specific route information reactively.
/**
* Utility composables for common route data access patterns
*/
function useRouteParams(): ComputedRef<Dictionary<string>>;
function useRouteQuery(): ComputedRef<Dictionary<string | (string | null)[]>>;
function useRoutePath(): ComputedRef<string>;
function useRouteName(): ComputedRef<string | null | undefined>;Usage Examples:
// Custom utility composables (can be created)
import { useRoute } from 'vue-router/composables';
import { computed } from 'vue';
// Create reusable route utilities
function useRouteParams() {
const route = useRoute();
return computed(() => route.params);
}
function useRouteQuery() {
const route = useRoute();
return computed(() => route.query);
}
function useRoutePath() {
const route = useRoute();
return computed(() => route.path);
}
export default {
setup() {
const params = useRouteParams();
const query = useRouteQuery();
const path = useRoutePath();
// Type-safe parameter access
const userId = computed(() => params.value.id);
const tab = computed(() => query.value.tab || 'profile');
// Derived state
const breadcrumbs = computed(() =>
path.value.split('/').filter(Boolean).map((segment, i, arr) => ({
name: segment,
path: '/' + arr.slice(0, i + 1).join('/')
}))
);
return {
userId,
tab,
breadcrumbs
};
}
};Create reusable navigation functions.
/**
* Navigation utility composables
*/
function useNavigation(): {
push: (to: RawLocation) => Promise<Route>;
replace: (to: RawLocation) => Promise<Route>;
go: (n: number) => void;
back: () => void;
forward: () => void;
};Usage Examples:
import { useRouter } from 'vue-router/composables';
// Create navigation utilities
function useNavigation() {
const router = useRouter();
return {
push: (to) => router.push(to),
replace: (to) => router.replace(to),
go: (n) => router.go(n),
back: () => router.back(),
forward: () => router.forward()
};
}
// Specialized navigation composables
function useUserNavigation() {
const { push } = useNavigation();
const goToUser = (id) => push({ name: 'user', params: { id }});
const goToUserEdit = (id) => push({ name: 'user-edit', params: { id }});
const goToUserPosts = (id) => push({ name: 'user-posts', params: { id }});
return {
goToUser,
goToUserEdit,
goToUserPosts
};
}
export default {
setup() {
const { back, forward } = useNavigation();
const { goToUser } = useUserNavigation();
const handleUserClick = (user) => {
goToUser(user.id);
};
return {
back,
forward,
handleUserClick
};
}
};Using composables with Vue 2.7+ or composition API plugin.
/**
* Installation requirements for composables
*/
interface ComposableSetup {
/** Vue 2.7+ has built-in composition API */
vue27Plus: boolean;
/** Or use @vue/composition-api plugin */
compositionApiPlugin: boolean;
}Usage Examples:
// With Vue 2.7+
import { createApp } from 'vue';
import VueRouter from 'vue-router';
const app = createApp({});
app.use(VueRouter);
// With @vue/composition-api plugin (Vue < 2.7)
import Vue from 'vue';
import VueCompositionApi from '@vue/composition-api';
import VueRouter from 'vue-router';
Vue.use(VueCompositionApi);
Vue.use(VueRouter);
// Component using composables
import { useRouter, useRoute } from 'vue-router/composables';
export default {
setup() {
// Must be called inside setup() function
const router = useRouter();
const route = useRoute();
// Error: Cannot be called outside setup()
// const router = useRouter(); // This would throw error
return {
// Expose to template if needed
};
}
};Handle navigation errors in composition API context.
/**
* Error handling patterns for composables
*/
interface ComposableErrorHandling {
navigationErrors: Promise<NavigationFailure | undefined>;
guardErrors: Error | NavigationFailure;
}Usage Examples:
import { useRouter } from 'vue-router/composables';
import { isNavigationFailure, NavigationFailureType } from 'vue-router';
import { ref } from 'vue';
export default {
setup() {
const router = useRouter();
const navigationError = ref(null);
const navigateWithErrorHandling = async (to) => {
try {
await router.push(to);
navigationError.value = null;
} catch (error) {
if (isNavigationFailure(error, NavigationFailureType.aborted)) {
console.log('Navigation was aborted');
} else if (isNavigationFailure(error, NavigationFailureType.duplicated)) {
console.log('Already at destination');
} else {
navigationError.value = error;
console.error('Navigation failed:', error);
}
}
};
// Guard error handling
onBeforeRouteLeave((to, from, next) => {
try {
// Some validation that might throw
validateBeforeLeave();
next();
} catch (error) {
console.error('Leave guard error:', error);
next(false);
}
});
return {
navigateWithErrorHandling,
navigationError
};
}
};interface ComputedRef<T> {
readonly value: T;
}
interface Ref<T> {
value: T;
}
type Dictionary<T> = { [key: string]: T };
interface NavigationGuard {
(to: Route, from: Route, next: NavigationGuardNext): any;
}
type NavigationGuardNext = (to?: RawLocation | false | ((vm: Vue) => any) | void) => void;Install with Tessl CLI
npx tessl i tessl/npm-vue-router