Vue Router
Routing in Vue is its own official package (vue-router), like React Router was a separate install — but the concepts are now thoroughly familiar from both the React and Angular courses. Define routes mapping paths to components, render the matched one in an outlet, link without reloading, read params, navigate from code, and guard routes. Same ideas, Vue's API.
Defining Routes
Routes are an array of { path, component } objects, the same shape as Angular's route config and React Router's <Route> list. :id is a dynamic segment; /:pathMatch(.*)* is Vue Router's (slightly cryptic) catch-all for unmatched URLs. createWebHistory() enables clean URLs (no #). The router is then registered in main.js with app.use(router) — the same plugin pattern Pinia will use next chapter.
RouterView and RouterLink
<RouterView /> is the outlet where the matched route's component renders — the equivalent of React Router's <Outlet /> and Angular's <router-outlet>. <RouterLink to="/about"> navigates without a full page reload, like React's <Link> and Angular's routerLink. A RouterLink automatically gets an active CSS class when its route is current, so highlighting the active nav item needs no manual URL comparison.
Reading Route Params with useRoute
useRoute() returns the current route object; route.params.id reads the :id segment — the equivalent of React Router's useParams() and Angular's ActivatedRoute.paramMap. The route object is reactive, so if the same component stays mounted while only the param changes (navigating /product/1 → /product/2), a watch (Chapter 5) on route.params.id reacts to that change.
Programmatic Navigation with useRouter
useRouter() returns the router instance; router.push(...) navigates from code — after a form submits, a login succeeds, an action completes — the equivalent of React Router's useNavigate() and Angular's Router.navigate(). Note the two distinct hooks: useRoute (singular, the current route's data) vs useRouter (the router, for navigating) — an easy pair to mix up by name.
Navigation Guards
A navigation guard runs before each route change — beforeEach receives the target (to) and current (from) routes, and either allows navigation (return true or nothing) or redirects (return a path). This is Vue's equivalent of Angular's canActivate guard, and the standard way to keep unauthenticated users out of protected pages. Guards can also be defined per-route (beforeEnter) or inside a component.
loadComponent, Vue Router supports lazy-loading a route's component so its code only downloads when the route is first visited: { path: '/admin', component: () => import('../views/Admin.vue') }. A dynamic import() as the component is all it takes — no separate Suspense boundary needed (the React equivalent from Advanced Chapter 3). This is the standard way to keep the initial bundle small.
<a href="/about"> instead of <RouterLink to="/about"> triggers a real full-page reload, throwing away all in-memory state — the same warning as React Router and Angular. RouterLink intercepts the click and updates the URL via the History API without a reload. Always use it for in-app navigation.
| Vue Router | React Router | Angular |
|---|---|---|
| routes array + createRouter | <Routes>/<Route> | routes + provideRouter |
| <RouterView /> | <Outlet /> | <router-outlet> |
| <RouterLink to> | <Link to> | routerLink |
| useRoute().params | useParams() | ActivatedRoute.paramMap |
| useRouter().push() | useNavigate() | Router.navigate() |
| beforeEach guard | Hand-rolled wrapper | canActivate |
Coding Challenges
Set up a 3-page app (Home, About, Contact) with a routes array, a nav using RouterLink, a RouterView, and a catch-all route showing a NotFound component for unmatched URLs.
📄 View solutionAdd a /product/:id route. From a product list, use RouterLink to navigate to a detail page that reads the id via useRoute and displays the matching product.
📄 View solutionAdd a beforeEach navigation guard protecting a /dashboard route, redirecting to /login when a simple isLoggedIn flag is false, with a button toggling the flag to test both outcomes.
📄 View solutionChapter 11 Quick Reference
- createRouter + a routes array (path → component); register with
app.use(router) - <RouterView /> renders the matched route; <RouterLink to> navigates without reload
- :id dynamic segments; /:pathMatch(.*)* is the catch-all route
- useRoute() — current route data (
route.params.id); useRouter() — navigate (router.push) - beforeEach((to, from) => ...) — a navigation guard; return a path to redirect, true/nothing to allow
- Lazy-load a route with
component: () => import('...')— built-in code splitting - Always use
RouterLink, never a plain<a href>, for in-app navigation - Next chapter: state management with Pinia, plus a data-fetching pattern (final chapter)