Navigation guards are a powerful feature in Vue Router that allow you to control the navigation flow of your application. They enable you to perform checks or actions before a route is entered, after a route is entered, or when navigating away from a route. This is particularly useful for tasks such as authentication, authorization, and data fetching.

Types of Navigation Guards

Vue Router provides several types of navigation guards:

  1. Global Guards: These are applied to every route in the application.
  2. Per-Route Guards: These are defined directly in the route configuration.
  3. In-Component Guards: These are defined within the component itself.

Global Guards

Global guards are registered using the router.beforeEach, router.beforeResolve, and router.afterEach methods.

  • beforeEach: This guard is called before every navigation.
  • beforeResolve: This guard is called after beforeEach and before the route is confirmed.
  • afterEach: This guard is called after every navigation is confirmed.

Example: Global beforeEach Guard

const router = new VueRouter({
  routes: [
    { path: '/home', component: Home },
    { path: '/about', component: About },
    { path: '/dashboard', component: Dashboard }
  ]
});

router.beforeEach((to, from, next) => {
  console.log('Navigating to:', to.path);
  console.log('Navigating from:', from.path);
  // Perform some check
  if (to.path === '/dashboard' && !isAuthenticated()) {
    next('/home'); // Redirect to home if not authenticated
  } else {
    next(); // Proceed to the route
  }
});

function isAuthenticated() {
  // Replace with real authentication check
  return false;
}

new Vue({
  router,
  render: h => h(App)
}).$mount('#app');

Per-Route Guards

Per-route guards are defined directly in the route configuration using the beforeEnter property.

Example: Per-Route beforeEnter Guard

const routes = [
  {
    path: '/dashboard',
    component: Dashboard,
    beforeEnter: (to, from, next) => {
      if (!isAuthenticated()) {
        next('/home'); // Redirect to home if not authenticated
      } else {
        next(); // Proceed to the route
      }
    }
  }
];

const router = new VueRouter({
  routes
});

new Vue({
  router,
  render: h => h(App)
}).$mount('#app');

In-Component Guards

In-component guards are defined within the component itself using the beforeRouteEnter, beforeRouteUpdate, and beforeRouteLeave lifecycle hooks.

  • beforeRouteEnter: Called before the route that renders this component is confirmed.
  • beforeRouteUpdate: Called when the route that renders this component has changed, but the component is reused.
  • beforeRouteLeave: Called when the route that renders this component is about to be navigated away from.

Example: In-Component Guard

const Dashboard = {
  template: '<div>Dashboard</div>',
  beforeRouteEnter(to, from, next) {
    if (!isAuthenticated()) {
      next('/home'); // Redirect to home if not authenticated
    } else {
      next(); // Proceed to the route
    }
  },
  beforeRouteLeave(to, from, next) {
    const answer = window.confirm('Do you really want to leave? You have unsaved changes!');
    if (answer) {
      next(); // Proceed to the route
    } else {
      next(false); // Cancel the navigation
    }
  }
};

const router = new VueRouter({
  routes: [
    { path: '/home', component: Home },
    { path: '/dashboard', component: Dashboard }
  ]
});

new Vue({
  router,
  render: h => h(App)
}).$mount('#app');

Practical Exercise

Exercise: Implementing a Navigation Guard

  1. Objective: Create a Vue application with a navigation guard that prevents access to a protected route unless the user is authenticated.
  2. Steps:
    • Set up a Vue application with Vue Router.
    • Create two routes: /home and /dashboard.
    • Implement a global beforeEach guard that checks if the user is authenticated before allowing access to the /dashboard route.
    • If the user is not authenticated, redirect them to the /home route.

Solution

// main.js
import Vue from 'vue';
import VueRouter from 'vue-router';
import App from './App.vue';
import Home from './components/Home.vue';
import Dashboard from './components/Dashboard.vue';

Vue.config.productionTip = false;
Vue.use(VueRouter);

const routes = [
  { path: '/home', component: Home },
  { path: '/dashboard', component: Dashboard }
];

const router = new VueRouter({
  routes
});

router.beforeEach((to, from, next) => {
  if (to.path === '/dashboard' && !isAuthenticated()) {
    next('/home'); // Redirect to home if not authenticated
  } else {
    next(); // Proceed to the route
  }
});

function isAuthenticated() {
  // Replace with real authentication check
  return false;
}

new Vue({
  router,
  render: h => h(App)
}).$mount('#app');
<!-- App.vue -->
<template>
  <div id="app">
    <router-link to="/home">Home</router-link>
    <router-link to="/dashboard">Dashboard</router-link>
    <router-view></router-view>
  </div>
</template>

<script>
export default {
  name: 'App'
};
</script>
<!-- Home.vue -->
<template>
  <div>
    <h1>Home</h1>
  </div>
</template>

<script>
export default {
  name: 'Home'
};
</script>
<!-- Dashboard.vue -->
<template>
  <div>
    <h1>Dashboard</h1>
  </div>
</template>

<script>
export default {
  name: 'Dashboard'
};
</script>

Summary

In this section, we explored the concept of navigation guards in Vue Router. We learned about the different types of guards: global guards, per-route guards, and in-component guards. We also implemented practical examples to understand how to use these guards to control the navigation flow in a Vue.js application. Navigation guards are essential for tasks such as authentication and authorization, ensuring that users can only access certain routes under specific conditions.

© Copyright 2024. All rights reserved