Introduction to Vue Router
Tags: vue, javascript, beginners
Published: 2020-02-12 15:01:25

---
title: Introduction to Vue Router
published: true
description: Vue router is one of the most popular libraries for Vue.js. In this blog post, we explore its many features and how you can leverage them.
tags: vue, javascript, beginners
canonical_url: https://blog.jscrambler.com/introduction-to-vue-router/
cover_image: https://blog.jscrambler.com/content/images/2020/02/jscrambler-blog-introduction-to-vue-router.jpg
---

To create a single-page app with Vue.js, we have to add a router library to route URLs to our components.

Vue.js has a Vue Router routing library made specifically to handle this routing.

In this article, we'll take a look at how to use the Vue Router in our Vue.js app.

## Getting Started

We can get started by including Vue and Vue Router scripts in our app's page. Then, we have to add a `div` to house our Vue app. Also, we have to include the `router-view` component to view the route's content.

To add links, we add `router-link` components with the path that we want to go to.

To do all that, we write the following:

`index.html`:

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://unpkg.com/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
  </head>
  <body>
    <div id="app">
      <router-link to="/foo">Foo</router-link>
      <router-link to="/bar">Bar</router-link>
      <div>
        <router-view></router-view>
      </div>
    </div>
    <script src="./index.js"></script>
  </body>
</html>

```

In the code above, we have the `script` tags for Vue and Vue Router in the `head` tag. Then, we have the `div` with ID `app` to house the Vue app.

The `router-view` is showing our content.

Inside the `div`, we have the `router-link` components with the `to` prop to pass in the path that we want the links to go to.

`router-link` is a component that comes with Vue Router.

Finally, we have our `index.js` script file. In there, we'll add our code for the route components and do the routing.

In `index.js`, we have:

```javascript
const Foo = { template: "<div>foo</div>" };
const Bar = { template: "<div>bar</div>" };
const routes = [
  { path: "/foo", component: Foo },
  { path: "/bar", component: Bar }
];

const router = new VueRouter({
  routes
});

const app = new Vue({
  router,
  el: "#app"
});
```

In the code above, we have the `Foo` and `Bar` routes to show 'foo' and 'bar' respectively.

Then, we use the `routes` array to map the components to the paths which we want to map the routes to.

Next, we created a new instance of `VueRouter` with an object that has our `routes` in it.

Then, we created a new `Vue` instance with the `router` object and an `el` property with the `#app` div that we added to house our app.

Once we did all that, we should have links on the top of the page that show 'Foo' and 'Bar' links respectively. When we click them, we'll see 'foo' and 'bar' respectively.

## Dynamic Route Matching

To map routes to a dynamic URL parameter, we can add a placeholder for it by creating a name and adding a colon before it.

Then, in our `Vue` instance, we can watch the `$route` object for changes in the parameter and run code accordingly.

For instance, we can write the following code to use route parameters in our routes:

`index.js`:

```javascript
const User = {
  template: "<div>User {{id}}</div>",
  data() {
    return {
      id: undefined
    };
  },
  watch: {
    $route(to, from) {
      this.id = to.params.id;
    }
  }
};

const routes = [
    { path: "/user/:id", component: User }
];

const router = new VueRouter({
  routes
});

const app = new Vue({
  router,
  el: "#app"
});
```

`index.html`:

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://unpkg.com/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
  </head>
  <body>
    <div id="app">
      <router-link to="/user/1">User 1</router-link>
      <router-link to="/user/2">User 2</router-link>
      <router-view></router-view>
    </div>
    <script src="./index.js"></script>
  </body>
</html>
```

In the code above, we have:

```javascript
watch: {
    $route(to, from) {
      this.id = to.params.id;
    }
 }
```

to watch for URL parameter changes. We get the `:id` route parameter by using `to.params.id`.

Then, we set that to `this.id` so that we can use it in our template, which is:

```html
<div>User {{id}}</div>
```

To define the routes, we have:

```javascript
const routes = [
    { path: "/user/:id", component: User }
];
```

The `:id` part of the string is the URL parameter placeholder.

In `index.html`, we have 2 `router-link` components:

```html
<router-link to="/user/1">User 1</router-link>
<router-link to="/user/2">User 2</router-link>
```

When we click them, we should see `id` in our template update as the `:id` route parameter is changing.

## Catch-all / 404 Not Found Route

We can use the `*` sign as a wildcard character.

To use it, we can write:

`index.html`

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://unpkg.com/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
  </head>
  <body>
    <div id="app">
      <router-view></router-view>
    </div>
    <script src="./index.js"></script>
  </body>
</html>

```

`index.js`

```javascript
const NotFound = {
  template: "<div>not found</div>"
};

const routes = [{ path: "*", component: NotFound }];

const router = new VueRouter({
  routes
});

const app = new Vue({
  router,
  el: "#app"
});
```

In the code above, we have the `NotFound` component, which is the component for our catch-all route since we have:

```javascript
{ path: "*", component: NotFound }
```

in the `routes` array.

Therefore, when we go to any URL, we'll see 'not found' displayed.

## Nested Routes

We can nest routes by adding a `children` property to our route entries with our child routes.

For example, we can write the following to create our nested routes:

`index.js`:

```javascript
const User = {
  template: `<div>
    User {{id}}
    <router-view></router-view>
  </div>`,
  data() {
    return {
      id: undefined
    };
  },
  watch: {
    $route(to, from) {
      this.id = to.params.id;
    }
  }
};

const Profile = {
  template: `<div>Profile</div>`
};

const routes = [
  {
    path: "/user/:id",
    component: User,
    children: [
      {
        path: "profile",
        component: Profile
      }
    ]
  }
];

const router = new VueRouter({
  routes
});

const app = new Vue({
  router,
  el: "#app"
});
```
`index.html`:

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://unpkg.com/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
  </head>
  <body>
    <div id="app">
      <router-link to="/user/1">User</router-link>
      <router-link to="/user/1/profile">Profile</router-link>
      <router-view></router-view>
    </div>
    <script src="./index.js"></script>
  </body>
</html>
```

The difference between the nested route example above and the earlier examples is that we have the following `routes` definition:

```javascript
const routes = [
  {
    path: "/user/:id",
    component: User,
    children: [
      {
        path: "profile",
        component: Profile
      }
    ]
  }
];
```

The `children` property is used to nest our child routes.

In the template for the `User` component, we have the `router-view` added as follows to display items in child routes:

```html
<div>
   User {{id}}
   <router-view></router-view>
</div>
```

We also have the following `router-link` components:

```html
<router-link to="/user/1">User</router-link>
<router-link to="/user/1/profile">Profile</router-link>
```

## Multiple Router Views
In order to have multiple `router-view` components in the same app, we have to name them.

We can define our routes as follows and put them in their own `router-view`:

`index.js`:

```javascript
const Foo = {
  template: `<div>foo</div>`
};

const Bar = {
  template: `<div>bar</div>`
};

const Baz = {
  template: `<div>baz</div>`
};

const router = new VueRouter({
  routes: [
    {
      path: "/",
      components: {
        default: Foo,
        a: Bar,
        b: Baz
      }
    }
  ]
});

const app = new Vue({
  router,
  el: "#app"
});
```
`index.html`:

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://unpkg.com/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
  </head>
  <body>
    <div id="app">
      <router-view></router-view>
      <router-view name="a"></router-view>
      <router-view name="b"></router-view>
    </div>
    <script src="./index.js"></script>
  </body>
</html>
```

<a href="https://blog.jscrambler.com/how-to-protect-your-vue-js-application-with-jscrambler/?utm_source=dev.to&utm_medium=referral" target="_blank"><img alt="Protect your Vue App with Jscrambler" src="https://media.jscrambler.com/blog/V1-Vue.jpg"></a>

In the code above, we have the `router-view` named `a` and `router-view` named `b` defined as in `index.html`:

```html
<router-view></router-view>
<router-view name="a"></router-view>
<router-view name="b"></router-view>
```

Then, in our `routes` definition in `index.js`, we have:

```javascript
components: {
    default: Foo,
    a: Bar,
    b: Baz
}
```

to map the `router-view` with no name to the `Foo` component, the `a` `router-view` to the `Bar` component and the `b` `router-view` to the `Baz` component.

Then we should see:

```txt
foo
bar
baz
```

displayed on the screen.

## Navigation Guards

From the official [Vue Router docs](https://router.vuejs.org/guide/advanced/navigation-guards.html):

> Navigation guards provided by vue-router are primarily used to guard navigations either by redirecting it or canceling it.

As such, we can add navigation guards to our routes to watch for route changes and do something before it's complete.

Enter/leave navigation guards won't trigger during params or query changes.

### Global Navigation Guards
We can define a global before guard by attaching a route change listener to our `router`.

To add a global navigation guard, we can write the following:

`index.js`:

```javascript
const Foo = {
  template: `<div>foo</div>`
};

const Bar = {
  template: `<div>bar</div>`
};

const Login = {
  template: `<div>login</div>`
};

const router = new VueRouter({
  routes: [
    {
      path: "/foo",
      component: Foo
    },
    {
      path: "/bar",
      component: Bar
    },
    {
      path: "/login",
      component: Login
    }
  ]
});

router.beforeEach((to, from, next) => {
  if (!localStorage.getItem("authToken") && to.path !== "/login") {
    return next("/login");
  }
  next();
});

const app = new Vue({
  router,
  el: "#app"
});
```

`index.html`:

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://unpkg.com/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
  </head>
  <body>
    <div id="app">
      <router-link to="/foo">Foo</router-link>
      <router-link to="/bar">Bar</router-link>
      <router-view></router-view>
    </div>
    <script src="./index.js"></script>
  </body>
</html>
```

In the code above, we have:

```javascript
router.beforeEach((to, from, next) => {
  if (!localStorage.getItem("authToken") && to.path !== "/login") {
    return next("/login");
  }
  next();
});
```

which is our global navigation guard that runs before navigation begins as indicated by the `beforeEach` call.

We check that the path that we're going to isn't `/login` with:

```javascript
to.path !== "/login"
```

Then, if `localStorage.getItem("authToken")` is false, we go to the `/login` route by calling `next('./login)`. Otherwise, we proceed by calling `next()`.

### Per-Route Guard
In a similar way, we can define per-route guards as follows:

```javascript
const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      beforeEnter: (to, from, next) => {
        // ...
      }
    }
  ]
})
```

These are called before navigation is done and only run when we try to go to the `/foo` route.

### In-Component Guards
We can define in-components in our component as follows:

```javascript
const Foo = {
  template: `...`,
  beforeRouteEnter (to, from, next) {
    //...
  },
  beforeRouteUpdate (to, from, next) {
    //...
  },
  beforeRouteLeave (to, from, next) {
    //...
  }
}
```

We have 3 guards. They are:

*`beforeRouteEnter` - it's called before the route renders the component
*`beforeRouteUpdate` - it's called when a route that renders the component has changed, including parameter changes.
*`beforeRouteLeave` - it's called when the rendered route is about to be navigated away from.

## Transitions
We can add `transition` components like any other component to add transitions to `router-view`.

To add transitions to a Vue app, we can use the `transition` component and some simple CSS:

`styles.css`:

```css
.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.9s;
}
.fade-enter,
.fade-leave-to {
  opacity: 0;
}
```

`index.js`:

```javascript
const Foo = {
  template: `<div>foo</div>`
};

const Bar = {
  template: `<div>bar</div>`
};

const router = new VueRouter({
  routes: [
    {
      path: "/foo",
      component: Foo
    },
    {
      path: "/bar",
      component: Bar
    }
  ]
});

const app = new Vue({
  router,
  el: "#app"
});
```

`index.html`:

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://unpkg.com/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
    <link rel="stylesheet" href="./styles.css" />
  </head>
  <body>
    <div id="app">
      <router-link to="/foo">Foo</router-link>
      <router-link to="/bar">Bar</router-link>
      <transition name="fade">
        <router-view></router-view>
      </transition>
    </div>
    <script src="./index.js"></script>
  </body>
</html>
```

In the code above, we added the styles in `styles.css` to create our CSS route transition effects. We just changed the opacity for a short moment to add the fade effect.

Then, we added the `transition` component with the `name` attribute set to `fade` so that we can use the classes with the `fade-` prefix in `styles.css` to style the transition effects.

In the end, when we click on the `router-link`, we'll see the fade effect.

## Conclusion

We can use Vue Router to map URL paths to components.

To get route params, we watch the `$route` object in our components.

We can also add nested routes by adding a `children` property with nested routes.

Also, we can add a `components` property to our route and name our `router-view` to add multiple `router-view`.

To intercept navigation and do something, we can add navigation guards for various stages of navigation.

Finally, we can use the `transition` component with some CSS to create route transition effects.

---

**Before deploying your commercial or enterprise Vue apps to production, make sure you are protecting their code against reverse-engineering, abuse, and tampering by following <a href="https://blog.jscrambler.com/how-to-protect-your-vue-js-application-with-jscrambler/?utm_source=dev.to&utm_medium=referral">this tutorial</a>**.