Any multi-page single-page app needs client-side routing, and Vue Router is the official solution.
Vue Router maps URL paths to components. You create a router with a history mode and a route table, install it with app.use(router), and render the matched component with <RouterView />:
const router = createRouter({
history: createWebHistory(),
routes: [
{ path: '/', component: Home },
{ path: '/users/:id', name: 'user', component: () => import('./UserPage.vue') },
],
})createWebHistory()gives clean URLs (the server must serveindex.htmlfor unknown paths);createWebHashHistory()uses#/URLs and needs no server config.() => import(...)lazy-loads a route's component as a separate chunk.- Dynamic segments like
:idappear inuseRoute().params.id. The same component instance is reused when only params change, so watch() => route.params.idto reload data. - Nested routes use
childrenplus a<RouterView />inside the parent component.
Navigate declaratively with <RouterLink :to="{ name: 'user', params: { id: 7 } }"> (it adds active classes) or programmatically with useRouter().push('/').
Navigation guards control access: router.beforeEach((to) => { if (to.meta.requiresAuth && !isLoggedIn()) return { name: 'login' } }). Return false to cancel, a route to redirect, or nothing to continue. Per-component hooks like onBeforeRouteLeave help with "unsaved changes" prompts.
Example
// router.js
import { createRouter, createWebHistory } from 'vue-router'
import Home from './views/Home.vue'
export const router = createRouter({
history: createWebHistory(),
routes: [
{ path: '/', name: 'home', component: Home },
{ path: '/users/:id', name: 'user',
component: () => import('./views/User.vue'), // lazy chunk
meta: { requiresAuth: true } },
{ path: '/:pathMatch(.*)*', component: () => import('./views/NotFound.vue') },
],
})
router.beforeEach((to) => {
const loggedIn = Boolean(localStorage.getItem('token'))
if (to.meta.requiresAuth && !loggedIn) return { name: 'home', query: { next: to.fullPath } }
})
// main.js: createApp(App).use(router).mount('#app')
// App.vue: <RouterLink :to="{ name: 'user', params: { id: 7 } }">Me</RouterLink>
// <RouterView />
// User.vue: const route = useRoute(); route.params.id // '7'Remember
- Define routes,
app.use(router), render with<RouterView> - Lazy-load route components with
() => import(...) - Params are in
useRoute().params; watch them when the same component is reused - Guards return false, a redirect route, or nothing
Watch out for
- Fetching data only in
onMountedof a route component; navigating /users/1 to /users/2 reuses the instance and shows stale data.