Vue Router
Vue Router is the official client-side routing library for Vue.js, providing robust and declarative navigation for single-page applications. The current stable version is 5.0.4, primarily designed for Vue 3 projects. It generally follows a regular release cadence, with minor bug fixes and experimental features being integrated frequently, and major versions released less often but incorporating significant architectural changes or merges. A key differentiator of Vue Router 5 is the integration of `unplugin-vue-router` into its core, enabling file-system based routing and simplifying route definition by convention. This merge aims to streamline development workflows, reducing boilerplate compared to earlier versions and offering a more integrated experience for large-scale applications. It also provides strong TypeScript support out of the box, ensuring type safety for route definitions and navigation guards.
Common errors
-
Uncaught (in promise) NavigationDuplicated: Avoided redundant navigation to current location
cause Attempting to navigate to the same route (path and parameters) that the application is currently on, often triggered by `router.push()` or `RouterLink` clicks.fixCatch the promise returned by `router.push()` or `router.replace()` to handle navigation failures gracefully: `router.push(...).catch(err => { if (isNavigationFailure(err, NavigationFailureType.duplicated)) console.log('Duplicate navigation'); })`. Alternatively, ensure your navigation logic only triggers when the target route is different. -
No match for current location: "/some/invalid/path"
cause The URL in the browser does not match any defined route in your `routes` array. This often happens with incorrect paths, typos, or missing catch-all routes.fixEnsure all intended paths are explicitly defined in your router's `routes` configuration. For unhandled paths, add a catch-all route (e.g., `{ path: '/:pathMatch(.*)*', name: 'NotFound', component: NotFoundComponent }`) as the last entry in your `routes` array to render a 404 page. -
Error: "[Vue Router warn]: Router must be installed explicitly using `app.use(router)`"
cause The Vue Router instance was created but not registered with the Vue application instance using `app.use()`.fixAfter creating your `router` instance with `createRouter()`, make sure to call `app.use(router)` on your Vue application instance before mounting it: `const app = createApp(App); app.use(router); app.mount('#app');`. -
Property '$route' does not exist on type '...' or 'Property '$router' does not exist on type '...'
cause TypeScript error indicating that the `$route` or `$router` properties are not recognized within a component. This often occurs in `<script setup>` contexts or when types are not correctly inferred/augmented.fixFor Composition API (`<script setup>`), use `useRoute()` and `useRouter()` hooks directly: `const route = useRoute(); const router = useRouter();`. For Options API, ensure your `tsconfig.json` correctly includes `vue-router/client` types and that global properties are properly augmented if necessary, though `this.$route` and `this.$router` usually work out of the box with `app.use(router)`.
Warnings
- breaking In Vue Router v5.0.3, experimental features `miss()` now throws internally and returns `never`, instead of returning an error instance. Additionally, `reroute()` was added, and `NavigationResult` has been deprecated, with `selectNavigationResult` being removed.
- breaking For developers migrating from `unplugin-vue-router` to Vue Router 5, import paths for the Vite plugin, data loaders, utility imports, and Volar plugins have changed.
- breaking The IIFE (Immediately Invoked Function Expression) build of Vue Router 5 no longer includes `@vue/devtools-api` because it has been upgraded to v8 and does not expose an IIFE build itself.
- breaking In an experimental breaking change from v5.0.0-beta.1, query parameters are now optional by default. This might alter how routes with optional query parameters are matched or handled.
- deprecated The `next()` callback with a string argument in navigation guards (e.g., `next('/path')`) has a deprecation warning in v5.0.3. It's recommended to use `next({ path: '/path' })` or `return '/path'` for better consistency and type safety.
- gotcha When using `createWebHistory`, server configuration is required to handle direct access to deep links (e.g., refreshing a non-root page). Without it, the server might return a 404 error.
Install
-
npm install vue-router -
yarn add vue-router -
pnpm add vue-router
Imports
- createRouter
import VueRouter from 'vue-router'
import { createRouter } from 'vue-router' - createWebHistory
import { createHistory } from 'vue-router'import { createWebHistory } from 'vue-router' - RouterView
import { RouterView } from 'vue-router' - useRouter
import { useRouter } from 'vue-router' - RouteLocationRaw
import type { RouteLocationRaw } from 'vue-router'
Quickstart
import { createApp } from 'vue'
import { createRouter, createWebHistory } from 'vue-router'
import App from './App.vue'
// 1. Define route components.
const Home = { template: '<div>Home Page</div>' }
const About = { template: '<div>About Page</div>' }
const User = {
template: `
<div>
User {{ $route.params.id }}
<RouterLink :to="'/user/' + ($route.params.id as any) + '/profile'">Profile</RouterLink>
<RouterLink :to="'/user/' + ($route.params.id as any) + '/posts'">Posts</RouterLink>
<RouterView />
</div>
`
}
const UserProfile = { template: '<div>User Profile</div>' }
const UserPosts = { template: '<div>User Posts</div>' }
const NotFound = { template: '<div>404 Not Found</div>' }
// 2. Define some routes
// Each route should map to a component.
const routes = [
{ path: '/', component: Home },
{ path: '/about', component: About },
{
path: '/user/:id',
component: User,
children: [
{ path: 'profile', component: UserProfile },
{ path: 'posts', component: UserPosts },
]
},
{ path: '/:pathMatch(.*)*', name: 'NotFound', component: NotFound },
]
// 3. Create the router instance and pass the `routes` option
const router = createRouter({
// 4. Provide the history implementation to use.
history: createWebHistory(process.env.BASE_URL ?? '/'),
routes, // short for `routes: routes`
})
// 5. Create and mount the root instance.
const app = createApp(App)
app.use(router)
app.mount('#app')
/* In your App.vue template: */
// <template>
// <h1>Hello Vue Router!</h1>
// <nav>
// <RouterLink to="/">Go to Home</RouterLink>
// <RouterLink to="/about">Go to About</RouterLink>
// <RouterLink to="/user/123">Go to User 123</RouterLink>
// <RouterLink to="/non-existent">Go to 404</RouterLink>
// </nav>
// <main>
// <RouterView />
// </main>
// </template>
// <script setup lang="ts">
// import { RouterLink, RouterView } from 'vue-router'
// </script>