Vue Routing

Map URLs to Vue views and navigate without full page reloads.

Overview

Routing decides which component to display for the current URL. Vue Router is Vue's official client-side routing library, enabling Single Page Applications to navigate between views while preserving browser history and updating only the changing application content.

Key concepts

  • Routes connect URL paths to components
  • RouterLink performs client-side navigation
  • RouterView renders the matched view
  • Dynamic parameters support reusable detail pages

What is Routing?

Routing maps a URL to a page-level component. When the URL changes, Vue Router selects the matching route and updates the routed portion of the interface.

Output
/               Home Page
/about          About Page
/contact        Contact Page
/products       Products Page
/products/42    Product 42

Why do we need Routing?

An online learning platform may contain Home, Courses, Tutorials, Blog, and Contact views. Routing gives each view a shareable URL, supports browser back and forward controls, and prevents all content from becoming one long page.

What is Vue Router?

Vue Router synchronizes the URL and displayed component. Internal navigation can occur without requesting a completely new HTML document, producing a smooth Single Page Application experience.

Installing Vue Router

A create-vue project can include Router during setup. Add it later with npm when it is not already installed.

Output
npm install vue-router

Creating Page Components

Route-level components are commonly stored in src/views while smaller reusable UI remains in src/components.

Output
src/
 components/
 router/
    index.js
 views/
    HomeView.vue
    AboutView.vue
    ProductView.vue
 App.vue
 main.js

Creating Routes

JavaScript
import { createRouter, createWebHistory } from "vue-router";
import HomeView from "../views/HomeView.vue";
import AboutView from "../views/AboutView.vue";

const routes = [
  {
    path: "/",
    name: "home",
    component: HomeView
  },
  {
    path: "/about",
    name: "about",
    component: AboutView
  }
];

const router = createRouter({
  history: createWebHistory(),
  routes
});

export default router;

Named routes decouple navigation from literal path strings and make future URL changes easier to manage.

Registering the Router

Install the router plugin before mounting the app.

JavaScript
import { createApp } from "vue";
import App from "./App.vue";
import router from "./router";

createApp(App)
  .use(router)
  .mount("#app");

Creating Navigation Links

RouterLink renders accessible navigation and lets Vue Router handle internal route changes. Normal anchor elements remain appropriate for external websites, downloads, and resources outside the SPA.

Vue SFC
<template>
  <nav aria-label="Primary navigation">
    <RouterLink :to="{ name: 'home' }">Home</RouterLink>
    <RouterLink :to="{ name: 'about' }">About</RouterLink>
  </nav>
</template>

Displaying Routed Pages

RouterView is the outlet where Vue Router renders the component matched by the current URL.

Vue SFC
<template>
  <SiteHeader />
  <main>
    <RouterView />
  </main>
  <SiteFooter />
</template>

Dynamic Routes

A dynamic segment begins with a colon and captures part of the URL. One ProductView can display many products.

JavaScript
{
  path: "/products/:id",
  name: "product",
  component: () => import("../views/ProductView.vue"),
  props: true
}
HTML
<RouterLink :to="{ name: 'product', params: { id: product.id } }">
  {{ product.name }}
</RouterLink>

With props: true, the route parameter is passed to ProductView as a prop, reducing direct coupling to the router.

Reading Route Information

Vue SFC
<script setup>
import { useRoute } from "vue-router";

const route = useRoute();
console.log(route.params.id);
</script>

Programmatic Navigation

Use useRouter when navigation follows an action such as successful login or form submission.

JavaScript
import { useRouter } from "vue-router";

const router = useRouter();

async function finishCheckout() {
  await saveOrder();
  router.push({ name: "order-confirmation" });
}

Nested Routes

Nested routes render child views inside a parent RouterView, making them useful for dashboards and settings layouts.

JavaScript
{
  path: "/account",
  component: () => import("../views/AccountView.vue"),
  children: [
    { path: "", name: "account", component: AccountOverview },
    { path: "settings", name: "account-settings", component: AccountSettings }
  ]
}

Lazy Loading Routes

Dynamic imports create separate chunks that load only when a route is visited, reducing the initial JavaScript bundle.

JavaScript
{
  path: "/reports",
  component: () => import("../views/ReportsView.vue")
}

Navigation Guards

Guards can redirect users before navigation, for example when a route requires authentication. They improve UX but do not replace server-side authorization.

JavaScript
router.beforeEach((to) => {
  if (to.meta.requiresAuth && !authStore.isLoggedIn) {
    return {
      name: "login",
      query: { redirect: to.fullPath }
    };
  }
});

Not Found Route

JavaScript
{
  path: "/:pathMatch(.*)*",
  name: "not-found",
  component: () => import("../views/NotFoundView.vue")
}

History Modes and Hosting

HistoryURL styleHosting need
createWebHistory/aboutServer must fall back to index.html
createWebHashHistory/#/aboutUsually no fallback configuration

Web history produces cleaner URLs but the deployment host must return the SPA entry file for unknown application paths. Otherwise, refreshing a nested route can produce a server 404.

Real-life example

A travel app can map Home, Destinations, Packages, About, and Contact to named routes. A dynamic destination route reuses one view for every location, and navigation feels immediate because only routed content changes.

Common beginner mistakes

  • Forgetting app.use(router)
  • Omitting RouterView
  • Using anchors for internal SPA navigation
  • Creating duplicate routes instead of dynamic segments
  • Reading a route param once and missing later changes
  • Forgetting a not-found route
  • Deploying web history without server fallback
  • Treating client guards as security authorization

Best practices

  • Use meaningful route names
  • Keep route configuration organized
  • Lazy-load page-level views
  • Prefer named navigation for internal links
  • Pass params as props when useful
  • Provide a not-found experience
  • Preserve browser back and forward behavior
  • Configure hosting for history mode
  • Enforce authorization on the server

Key takeaways

  • Routing maps URLs to views
  • Vue Router powers client-side Vue navigation
  • RouterLink navigates internally
  • RouterView renders the matched component
  • Dynamic segments reuse detail pages
  • Nested routes support layouts
  • Lazy loading reduces initial bundles
  • Guards control navigation flow
  • History mode requires correct hosting configuration
Let's learn with DevBrainBox AI