Vue Router Basics

Introduction

Vue Router adds client-side routing to Vue apps—change URLs without full page reloads, map paths to components, and pass route params. This chapter sets up createRouter, <RouterLink>, <RouterView>, dynamic segments, and programmatic navigation with useRouter.

Prerequisites

Router Setup

src/router/index.ts (typical create-vue layout):

src/main.ts:

typescript
import { createApp } from "vue";
import App from "./App.vue";
import router from "./router";
 
createApp(App).use(router).mount("#app");

src/App.vue:

vue
<template>
  <header>
    <nav>
      <RouterLink to="/">Home</RouterLink>
      <RouterLink to="/about">About</RouterLink>
    </nav>
  </header>
  <main>
    <RouterView />
  </main>
</template>

Code explanation:

  • createWebHistory uses real URLs (/about)—needs server fallback in production
  • RouterView renders the matched route component
  • RouterLink renders <a> with active class handling

Compare with Navigation and History in JavaScript—Router wraps the History API.

vue
<RouterLink to="/" active-class="nav-active" exact-active-class="nav-exact">
  Home
</RouterLink>

router-link-active / router-link-exact-active default classes.

Dynamic Route Params

typescript
{
  path: "/posts/:slug",
  name: "post-detail",
  component: () => import("../views/PostDetailView.vue"),
}

PostDetailView.vue:

vue
<script setup lang="ts">
import { computed } from "vue";
import { useRoute } from "vue-router";
 
const route = useRoute();
const slug = computed(() => route.params.slug as string);
</script>
 
<template>
  <h1>Post: {{ slug }}</h1>
</template>

route.params updates when navigating /posts/a/posts/b on same component—watch slug or use onBeforeRouteUpdate.

Programmatic Navigation

MethodBehavior
router.push()Navigate; adds history entry
router.replace()Navigate without new history entry
router.back()History back

Query String

typescript
router.push({ path: "/search", query: { q: "vue", page: "2" } });
// /search?q=vue&page=2

Read query:

typescript
const q = computed(() => route.query.q as string | undefined);

Nested Routes

Layout with child pages:

typescript
{
  path: "/dashboard",
  component: () => import("../layouts/DashboardLayout.vue"),
  children: [
    { path: "", name: "dashboard-home", component: () => import("../views/DashboardHome.vue") },
    { path: "settings", name: "dashboard-settings", component: () => import("../views/DashboardSettings.vue") },
  ],
},

DashboardLayout.vue:

vue
<template>
  <div class="dashboard">
    <aside>
      <RouterLink to="/dashboard">Overview</RouterLink>
      <RouterLink to="/dashboard/settings">Settings</RouterLink>
    </aside>
    <section>
      <RouterView />
    </section>
  </div>
</template>

Child routes render in nested <RouterView />.

Named Views (Awareness)

Multiple <RouterView name="sidebar"> for complex layouts—see official docs; one default view is enough for most apps.

Route Props (Optional)

Pass params as component props:

typescript
{
  path: "/posts/:id",
  component: PostView,
  props: true,
}
vue
<script setup lang="ts">
defineProps<{ id: string }>();
</script>

404 Catch-All

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

Place last in routes array.

History Mode vs Hash

ModeURLServer config
History (createWebHistory)/aboutSPA fallback required
Hash (createWebHashHistory)/#/aboutNo special config

Production SPAs usually prefer history + Nginx try_filesBuild and Deploy.

Practice Exercise

Add routes:

  1. /posts — list view
  2. /posts/:slug — detail view
  3. Link from list to detail with RouterLink

FAQ

<a> causes full page reload; RouterLink client navigation.

Component not updating on param change?

Same component reused—**watch route.params or key <RouterView :key="route.fullPath">.

Lazy import syntax?

() => import('./View.vue') code-splits route—Lazy Routes.

BASE_URL?

Vite import.meta.env.BASE_URL for apps hosted in subdirectory.

Multiple RouterView?

Nested routes use one per level in layout components.

Without create-vue router?

npm install vue-router, create router/index.ts, app.use(router).