Build seamless Single Page Applications.
1The Router Outlet
Vue Router uses <router-view> as a placeholder where the matched component for the current URL will be rendered. You can think of it as a dynamic <slot> that the router controls.
3useRoute vs useRouter
In the Composition API, useRoute() gives you information about the CURRENT route (params, query strings, path). useRouter() gives you the router INSTANCE, which has methods like .push() and .replace() to change pages programmatically.
4Step-by-Step Breakdown
Modern web apps don't actually reload the page when you click a link. They swap out components instantly. This is called a Single Page Application (SPA).
Vue uses the official vue-router library to handle this. You define "Routes" that map a URL to a Vue Component.
What do you define in Vue Router to tell the application which component to show when a user visits a specific URL?
- βlinks
- βroutes
- βpages
Once your router is set up, you use the <router-view> component in your App.vue. This is the "outlet" where the current page component will be rendered.
To navigate between pages, NEVER use a standard <a href="/about"> tag! That will cause a full page reload. Instead, use <router-link>.
Which built-in component should you use to create navigation links in a Vue SPA to prevent full page reloads?
- βa
- βrouter-link
- βnav-link
Sometimes you need Dynamic Routes, like /users/123. You define these using a colon : in the path.
Inside the component, you can access that ID using the useRoute() composable.
Which composable do you import from vue-router to access information about the current URL (like route parameters)?
- βuseRouter
- βuseRoute
- βgetRoute
Need to redirect a user after they log in? Use useRouter() to programmatically navigate.
Level Up π
Advanced cheat sheets, SEO tricks, and interview prep for this topic.
Browser Support
Fully supported.
Fully supported.
Fully supported.
Fully supported.
Accessibility (A11y)
1Managing Focus and Announcements on Route Change
Because vue-router swaps components without a full page reload, the browser never resets focus to the top of the page the way a traditional navigation does β production apps typically use router.afterEach to move focus to a heading or an aria-live region announcing the new page title, giving screen reader users equivalent feedback to a real page load.
router.afterEach((to) => {
document.getElementById('page-title')?.focus();
});SEO Implications
- 1
Client-Side Route Params Require SSR to Be Crawlable Reliably
A dynamic route like /users/:id resolved purely by vue-router in the browser still needs SSR (via Nuxt) or pre-rendering for each concrete /users/123, /users/456 URL to return meaningful HTML on first request β otherwise a crawler fetching that specific URL directly gets the same empty app shell regardless of which id was requested.
Best Practices
Lazy-Load Route Components
Define routes with a dynamic import (component: () => import('./UserProfile.vue')) instead of a static import, so vue-router and the bundler split each route into its own chunk and users only download the code for the page they actually visit.
Frequent Bugs
Using a plain <a href="/about"> instead of <router-link to="/about">.
A native anchor tag triggers a full browser navigation and reload, discarding the entire in-memory Vue application state, even though the URL is internal. Always use <router-link> (or router.push() programmatically) for in-app navigation.
Real-World Examples
Protecting a Dashboard Route with a Navigation Guard
A /dashboard route registers a beforeEnter guard that checks an auth store and calls next('/login') if the user isn't authenticated, centralizing the access check in the route definition instead of repeating an if check inside every dashboard-related component.
{
path: '/dashboard',
component: Dashboard,
beforeEnter: (to, from, next) => {
auth.isLoggedIn ? next() : next('/login');
}
}