When building a modern web application, being able to navigate between pages is a necessity. Not to mention it is very important to be able to do so easily. To make this possible, frameworks such as Angular, React, and Vue use what’s known as a router and a set of routes. Each possible point of navigation, or page, is a route with its own configuration.
We’re going to see how to configure a set of routes and navigate between them using Vue.js and the vue-router library.
If you’ve been keeping up with my content, you’ll remember I wrote something on the topic of navigation using Angular titled, Navigating a Web Application with the Angular Router. While being a completely different framework, some of the concepts carry over to Vue.js.
For simplicity, we’re going to create a fresh Vue.js project and work our way into a navigation example. For this particular example we’ll be using the Vue CLI to scaffold our project, so make sure it is installed and ready to go.
From the command line, execute the following:
vue init webpack router-project
During the project initialization, it doesn’t matter if you use standalone mode (runtime and compiler) or just runtime mode. Make sure that the vue-router is installed as we’ll be using it going forward. The linter and test packages are optional as we won’t be exploring them in this example.
Once the project has been created, execute the following:
cd router-project
npm install
At this point in time we can start the development of our Vue.js web application.
The Vue CLI will have created us a HelloWorld.vue file in the src/components directory. Go ahead and rename that file from HelloWorld.vue to page1.vue.
Open the project’s src/components/page1.vue file and include the following code:
<template>
<div class="hello">
<h1>{{ msg }}</h1>
</div>
</template>
<script>
export default {
name: 'Page1',
data () {
return {
msg: 'Welcome to Your Vue.js App'
}
}
}
</script>
<style scoped>
h1, h2 {
font-weight: normal;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
You’ll notice that the above code is just a stripped down version of what we got from scaffolding our project. Inside the <script>
tags, we did rename our component to Page1
. This name will be important when we configure the router.
Copy the src/components/page1.vue file to src/components/page2.vue. Our second route will more or less be the same as our first because we like to keep our examples simple.
The code in src/components/page2.vue should look like the following:
<template>
<div class="hello">
<h1>{{ msg }}</h1>
</div>
</template>
<script>
export default {
name: 'Page2',
data () {
return {
msg: 'Hey Nic Raboy'
}
}
}
</script>
<style scoped>
h1, h2 {
font-weight: normal;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
In the above code we’ve changed the component name and the message so it is obvious that we’ve navigated somewhere new. Nothing complicated has been added or changed that is different from the initial scaffold.
This is where the router configuration comes into play.
Open the project’s src/router/index.js file and include the following code:
import Vue from 'vue'
import Router from 'vue-router'
import Page1 from '@/components/page1'
import Page2 from '@/components/page2'
Vue.use(Router)
export default new Router({
routes: [
{
path: "/",
redirect: {
name: "Page1"
}
},
{
path: '/page1',
name: 'Page1',
component: Page1
},
{
path: '/page2',
name: 'Page2',
component: Page2
}
]
})
So what exactly is happening in the above router file?
First we’re importing the two components that we have Page1
and Page2
. Each of these components will be a route in our application, so they must be added to the routes
array of our new router.
Instead of setting Page1
as our default route, the logical choice is to redirect to it when the application loads at the root. Each route in the array receives a path
, a name
, and a matching component
. The path
is what shows in the URL bar and future navigation can happen either based on the path
or the name
.
Per the Vue CLI and the project scaffolding, the router is wired up via the project’s src/main.js file. Now we can worry about navigation within the application.
We have two components and two possible routes so it makes sense to navigate back and forth between them. Navigation can happen via markup or via JavaScript. We’re going to explore both possibilities.
Open the project’s src/components/page1.vue file. Within the <template>
section, we’re going to have the following:
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<router-link to="/page2">Navigate to Page2</router-link>
</div>
</template>
Notice in the above markup we have a <router-link>
tag. We’re saying that when the element is clicked, Vue will navigate to the router path indicated.
If you wanted to navigate based on the route name, the tag could easily be changed to the following:
<router-link :to="{ name: 'Page2' }">Navigate to Page2</router-link>
So that was navigation in Vue.js via markup. How about navigation via the JavaScript code?
Open the project’s src/components/page2.vue file and change the <script>
block to look like the following:
<script>
import router from '../router'
export default {
name: 'Page2',
data () {
return {
msg: 'Hey Nic Raboy'
}
},
methods: {
navigate() {
router.push({ name: "Page1" });
}
}
}
</script>
In the above code, notice that we’ve imported the file that contains our route configuration. With it, we can create a method called navigate
that will push a new navigation item into the stack. This time we’re navigating to Page1
.
We need something to call this navigate
method. Jump back to the <template>
block and make it look like the following:
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<a style="cursor: pointer; text-decoration: underline" v-on:click="navigate()">Navigate to Page1</a>
</div>
</template>
Notice that we have a v-on:click
event to call the navigate
method.
If you haven’t noticed, the push
that we did navigates forward in the navigation stack. This means that even though we navigated to Page1
from Page2
, we actually navigated to Page1
, rather than back to Page1
. This can be corrected by changing our navigate
method to the following:
methods: {
navigate() {
router.go(-1);
}
}
We can define exactly how many positions backwards we want to go.
You just saw how to configure and navigate between routes using the vue-router library in a Vue.js web application. Navigation can happen via markup or JavaScript code and whether or not the intention is to go backwards or forward can easily be defined.
In a future tutorial, we’ll explore how to pass data between routes during a navigation event. This is useful when creating master-detail type scenarios.