Vue Router 4 Fundamentals: Navigation, Parameters, and Guards

Routing in modern web applications enables dynamic, client-side navigation without full page reloads. In Vue 3 with Vue Router 4, routing is declarative, composable, and highly extensible—supporting SPA navigation, parameterized paths, conditional access, and lifecycle-aware logic.

Core Routing Concepts

A route maps a URL pattern to a component or set of components. It serves as the backbone for navigation, state management across views, and user experience continuity—especially critical in single-page applications where seamless transitions replace traditional server round-trips.

Redirect Configuration

Redirection reroutes navigation from one path to another before rendering. It’s commonly used to normalize URLs, handle legacy routes, or enforce canonical entry points.

In router.js:

import { createRouter, createWebHashHistory } from 'vue-router';
import Dashboard from '../views/Dashboard.vue';
import ItemList from '../views/ItemList.vue';
import NewItem from '../views/NewItem.vue';
import EditItem from '../views/EditItem.vue';

const router = createRouter({
  history: createWebHashHistory(),
  routes: [
    {
      path: '/',
      components: { default: Dashboard }
    },
    {
      path: '/items',
      components: { listSlot: ItemList }
    },
    {
      path: '/all-items',
      redirect: '/items' // Redirects /all-items → /items
    },
    {
      path: '/create',
      components: { formSlot: NewItem }
    },
    {
      path: '/edit/:id',
      components: { editSlot: EditItem }
    }
  ]
});

export default router;

In App.vue, multiple <router-view> slots render named components:

<template>
  <nav>
    <router-link to="/">Dashboard</router-link>
    <router-link to="/items">Items</router-link>
    <router-link to="/all-items">All Items (redirects)</router-link>
    <router-link to="/create">New</router-link>
  </nav>

  <main>
    <!-- Default view -->
    <router-view />

    <!-- Named views -->
    <section><h3>List Panel</h3><router-view name="listSlot" /></section>
    <section><h3>Form Panel</h3><router-view name="formSlot" /></section>
    <section><h3>Editor Panel</h3><router-view name="editSlot" /></section>
  </main>
</template>

Programmatic Navigation

Unlike static <router-link> elements, programmatic navigation uses the useRouter() composable to trigger navigation dynamically—ideal for form submissions, conditional redirects, or asynchronous workflows.

In App.vue:

<script setup>
import { useRouter } from 'vue-router';

const router = useRouter();
const targetPath = ref('/items');

const navigateToItems = () => {
  // Navigate by string path
  router.push('/items');

  // Or navigate using a location descriptor
  // router.push({ path: '/items', query: { filter: 'active' } });
};

const navigateWithParams = (id) => {
  router.push({ name: 'editItem', params: { id } });
};
</script>

<template>
  <button @click="navigateToItems">Go to Items</button>
  <button @click="navigateWithParams(42)">Edit Item #42</button>
</template>

Passing Data via Routes

Two primary strategies exist for passing data between routes: path parameters and query parameters.

1. Path Parameters

Define dynamic segments in route paths using colons (:id). These values are accesible via route.params.

Route definition:

{
  path: '/details/:lang/:version',
  name: 'languageDetail',
  component: LanguageDetail
}

In LanguageDetail.vue:

<script setup>
import { useRoute } from 'vue-router';
import { ref, onMounted } from 'vue';

const route = useRoute();
const language = ref(route.params.lang || 'unknown');
const version = ref(route.params.version || 'latest');

onMounted(() => {
  console.log(`Displaying ${language.value} v${version.value}`);
});
</script>

<template>
  <h2>{{ language }} (v{{ version }})</h2>
</template>

2. Query Praameters

Key-value pairs appended after ? in the URL (e.g., /search?term=vue&page=2). Accessed via route.query.

Navigation example:

router.push({
  path: '/search',
  query: { term: 'Vue Router', limit: '10' }
});

Inside the target component:

const route = useRoute();
console.log(route.query.term); // 'Vue Router'

Route Navigation Guards

Guards intercept navigation to enable authentication checks, data preloading, or confirmation prompts.

Global Before-Each Guard

Executes before every route change. Use it for authentication enforcement:

// router.js
router.beforeEach((to, from, next) => {
  const isAuthenticated = !!localStorage.getItem('authToken');

  if (to.meta.requiresAuth && !isAuthenticated) {
    next({ path: '/login', query: { redirect: to.fullPath } });
  } else if (to.path === '/login' && isAuthenticated) {
    next('/dashboard');
  } else {
    next();
  }
});

Add metadata to protected routes:

{
  path: '/dashboard',
  component: Dashboard,
  meta: { requiresAuth: true }
}

Global After-Each Hook

Fires after successful navigation—ideal for analytics, logging, or UI cleanup:

router.afterEach((to, from) => {
  document.title = to.meta.title || 'App';
  gtag('config', 'GA_MEASUREMENT_ID', { page_path: to.fullPath });
});

Authentication Flow Example

A login flow demonstrates guard integration:

  • Login.vue collects credentials and stores a session token on success.
  • Dashboard.vue reads the token and offers logout that clears storage and redirects.
  • The global guard blocks unauthenticated access to protected routes.

This pattern decouples authorization logic from individual components and centralizes security policy—ensuring consistent behavior across the application surface.

Tags: vue-router vue-3 client-side-routing route-guards programmatic-navigation

Posted on Sun, 24 May 2026 17:21:24 +0000 by dotwebbie