Navigation between views in Vue with Vue Router
Tags: vue, javascript, webdev, tutorial
Published: 2022-09-08 21:30:33

After [creating an application in Vue](https://fjolt.com/article/vue-create-your-first-app), you'll often want it to consist of multiple views or pages. To do this, we need to use an additional package known as `vue-router`. Creating a simple Vue application is easy, so in this guide we'll be looking at how you can add `vue-router` to your new application. To create your app in the first place, you only have to run the following commands:
```shell
npm i -g @vue/cli 
vue create my-app
```

Then, **adding a router** to your application so you can navigate between pages, is also equally easy. Simply run the following command as well:
```
vue add router
```

You may be asked if you want to use history mode. You can type `Y` to this, if you have no preference. After that, you'll get a few more folders and files in your project. Your overall structure should look a little like this:
```
- public
--- favicon.ico
--- index.html
- src
--- assets
--- components
--- router
------ index.js
--- views
------ About.vue
------ Home.vue
--- App.vue
--- main.js
- package.json
- package-lock.json
```

As you can see, you now have a number of new files for the router - and a few changes to your existing files. For example, in `main.js`, your application will be using the router folder that has now been created. The `index.js` file will be imported as shown below:
```javascript
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'

createApp(App).use(router).mount('#app')
```

## Modifying your Vue Router
In your `/router/index.js` file, you'll find the configuration for your router! It's here where you can set up pages. By default, you'll find your `router` looking a little like this:
```javascript
import { createRouter, createWebHistory } from 'vue-router'
import Home from '../views/Home.vue'

const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home
  },
  {
    path: '/about',
    name: 'About',
    // route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
  }
]

const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes
})

export default router
```

So there are two ways to add routes, as shown above. You can import using the `import()` function, or `import` using the typical Javascript `import` statement. Each `route` has 3 different parts:
- the `path`, which is the URL the user will be able to navigate to.
- the `name` of the page, which is the identifier for the page.
- the `component` for the page. This is the component which will appear when the user navigates to the `path`.

```
{
    path: '/',
    name: 'Home',
    component: Home
}
```

To add more, you just need to add more to the object - so below I've added in a new page called `/contact-us`, using a component found in `'../views/ContactUs.vue'`:

```javascript

import { createRouter, createWebHistory } from 'vue-router'
import Home from '../views/Home.vue'

const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home
  },
  {
    path: '/contact-us',
    name: 'ContactUs',
    component: () => import('../views/ContactUs.vue')
  },
  {
    path: '/about',
    name: 'About',
    // route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
  }
]

const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes
})

export default router
```

## Dynamic Routing with Vue Router
So, that's all good, but what if your URL endpoint isn't static? For example, `/user/:id`, where `:id` could be anything at all. Fortunately, that is also possible, simply by writing the URL in that format - you just have to write `/user/:id` in the `path` property:
```javascript
{
    path: '/user/:name',
    name: 'User',
    component: () => import('../views/User.vue')
}
```

The matching format for `vue-router` is familiar, if you've used `express` - and in fact any route matching you can do in `express`, you can do in `vue-router`.

### Redirection with Vue Router
**Finally**, we can also set a route to redirect to another one. You can do this using the `redirect` property. For example, the below will redirect `/home` to `/homepage`:
```javascript
{
    path: '/home',
    name: 'home',
    redirect: '/homepage'
}
```

This can also be defined as a named route. Below, we will redirect `/home` to whichever route has the name `about`:
```javascript
{
    path: '/home',
    name: 'home',
    redirect: { name: 'about' }
}
```

And finally, you can also define this as a function.. meaning you can create some more complex logic to handle the redirection:
```javascript
{
    path: '/user/:id',
    name: 'home',
    redirect: (to) => {
        // to will contain information about the route
        // to.params.id will be whichever `id` is in the URL in /user/:id
    }
}
```

## Navigating Between Pages with Vue Router
Now that we have defined our router, we'll want to use it in our application. You may notice that your `App.vue` file has changed slightly, and contains something like this:
```javascript
<template>
    <div id="nav">
        <router-link to="/">Home</router-link> |
        <router-link to="/about">About</router-link>
    </div>
    <router-view/>
</template>
```

The `<router-link>` tag can be used to easily navigate between routes defined in your router `index.js` file. The `<router-view>` tag will ultimately contain your routes, once they are clicked on. Each route will also contain their own `<router-view>`, though, which means you can have nested routes. These can all be defined in `/routes/index.js`. For example, here is a nested route where it contains two potential children, `dashboard`, and `posts`:
```javascript
const routes = [
    {
        path: '/user/:name',
        name: 'User',
        component: import('../views/User.vue'),
        children: [{
            path: 'dashboard',
            component: import('../views/Dashboard.vue'),
        },
        {
            path: 'posts',
            component: import('../views/Posts.vue'),
        }]
    }
]
```

Now, since we have defined child components, we can still use the `/user/:name` path, but now have two additional components which will be rendered within `User.vue`, accessible via `/user/:name/dashboard` and `/user/:name/posts` respectively. So while `User` is rendered within the App.vue `<router-view>`, `dashboard` and `posts` will be rendered within the `User.vue` version of `<router-view>`. It looks a bit like this:

```
┌ - - - - - - - - - - - - - - - - - - ┐
| App.vue                             |
| ┌ - - - - - - - - - - - - - - - - ┐ |
| | User.vue                        | | 
| | ┌ - - - - - - - ┐ ┌ - - - - - ┐ | |
| | | Dashboard.vue | | Posts.vue | | |
| | └ - - - - - - - ┘ └ - - - - - ┘ | |
| └ - - - - - - - - - - - - - - - - ┘ |
└ - - - - - - - - - - - - - - - - - - ┘
```

That ultimately means the `User.vue` component will always be visible when you navigate to `/user/:name`, but the `Dashboard.vue` and `Posts.vue` component will only become visible if you navigate to those routes!

### Programatic Routing with Vue Router
Just like how we used `<router-link>`, we can also programmatically navigate to a route using `router.push`. `<router-link to="/about">` can similarly be written like this in Javascript:
```javascript
router.push('/about')
```

If we want to be a little more advanced, we can pass in an object. For example, the below will navigate programmatically to the route with a `name` defined as `About`, and add a query string of `?id=15` to the end. If the `About` route has a `path` of `/about`, then the URL this will redirect to would be `/about/?id=15`:
```javascript
router.push({ name: 'About', query: { id : 15 }})
```

Similarly, the same Javascript could be represented in HTML as so:
```html
<router-link to="{ name: 'About', query: { id : 15 }}">About</router-link>
```

### Preventing the back button with Vue Router
**While** this will add a new history entry for the user navigating, we can also **replace** the current page for the user - which means that no history or back button to the previous page will be available. This is generally not advisable, but will have some limited use in some situations. To do that programmatically, we can use `router.replace`:
```javascript
router.replace({ name: 'About', query: { id : 15 }})
```

Or in HTML, append the `replace` attribute:
```html
<router-link to="{ name: 'About', query: { id : 15 }}" replace>About</router-link>
```


## Conclusion

I hope you've enjoyed this guide to getting started with the vue router. Routers in Vue are an invaluable part of setting up a new application, and give us so much flexibility to define and build pages within Vue. [To learn more about Vue, check out my other guides](https://fjolt.com/category/vue).