Building a Vue v2 JS app using Vue-router

Vue is a great javascript framework which I picked up to learn a couple of weeks back. I was after a simple framework which I could build an internal tool with and fortunately I came across Vue days after they released version 2. I wanted something quick, simple and (controversially for some) something that came with the ability to be executed client-side. Vue easily takes on the big names of React and Angular and has a easier learning curve for a developer new to the Javascript world of MVC (Model View Controller) apps.

This post will walk you through creating a client-side Vue JS app using Vue Router. Vue Router is a plugin for Vue which allows you to more easily add URLs and other routes to your Vue JS app. This blog assumes you have a basic knowledge of Vue.

At the end of this post, we will have an app which shows a team member list page and team member detail pages, each with their own unique URL

This tutorial uses Vue 2.0.3, Vue Router 2.0.1 and the data has been generated using JSON Generator. The data set we will be using consists of 7 people with the following attributes:

<span class="token punctuation">{</span>
    <span class="token string">"index"</span><span class="token punctuation">:</span> <span class="token number">0</span><span class="token punctuation">,</span>
    <span class="token string">"guid"</span><span class="token punctuation">:</span> <span class="token string">"ebee55c4-d685-4d77-a2bb-650283fb8753"</span><span class="token punctuation">,</span>
    <span class="token string">"picture"</span><span class="token punctuation">:</span> <span class="token string">"<a class="token url-link" href="http://placehold.it/32x32">http://placehold.it/32x32</a>"</span><span class="token punctuation">,</span>
    <span class="token string">"age"</span><span class="token punctuation">:</span> <span class="token number">20</span><span class="token punctuation">,</span>
    <span class="token string">"eyeColor"</span><span class="token punctuation">:</span> <span class="token string">"green"</span><span class="token punctuation">,</span>
    <span class="token string">"name"</span><span class="token punctuation">:</span> <span class="token string">"Hope Dennis"</span><span class="token punctuation">,</span>
    <span class="token string">"company"</span><span class="token punctuation">:</span> <span class="token string">"ZORK"</span><span class="token punctuation">,</span>
    <span class="token string">"email"</span><span class="token punctuation">:</span> <span class="token string">"<a class="token email-link" href="mailto:hopedennis@zork.com">hopedennis@zork.com</a>"</span><span class="token punctuation">,</span>
    <span class="token string">"address"</span><span class="token punctuation">:</span> <span class="token string">"127 Wortman Avenue, Corriganville, Marshall Islands, 5960"</span><span class="token punctuation">,</span>
    <span class="token string">"about"</span><span class="token punctuation">:</span> <span class="token string">"Labore velit deserunt sunt labore nisi reprehenderit voluptate consequat laboris id minim. Elit tempor occaecat sunt enim irure aliqua eiusmod minim. Ad culpa laborum laborum anim proident duis ullamco. Sit ipsum id esse proident sunt et dolor excepteur Lorem irure anim. Lorem nisi eiusmod pariatur qui duis sint minim dolore.\r\n"</span>
<span class="token punctuation">}</span>

The guid attribute will be used as the URL

Loop through data

The first step is to set up our Vue app, looping through the data and outputting the name of each of our users. If you’ve used Vue before, the following should look fairly familiar:

The above code is looping through the data and outputting the name attribute for each user. You could chose to output other details such as the email address or company name by inserting {{ person.email }} into the HTML code.

Create the listing component

When using Vue Router, it requires each "page" to be a Vue component. In preparation for this, let’s create a component for the user listing we've just created.

In the example above, I’ve made a template in the HTML using the <template> element - this is then referenced from the component using the id attribute. I found this was the neatest way of handling multi-line HTML and separating out template code from logic.

In the JS, the component has been called people-listing and includes both the template ID and the data from the parent Vue object. The component can then called using the new <people-listing /> HTML tag.

Create the detail view component

Let’s put aside the listing component and focus on the detail view. In order to display the correct person in our template, we need to select that person from the data array and create a component to display the data.

For this example, I’ve hard-coded a selectedID variable on the parent Vue object so we have a GUID (the guid variable) to match and select the correct person. Notice I have replaced the <people-listing /> element in the main app HTML with <people-detail />.

To find the correct person associated with the selectedID, the data is looped through in the people-detail component to select the appropriate person. Once found, the data is assigned to a variable and passed through to the component to display it. The HTML then features displays the content required.

Setup the router

Now we have our two components, we can include Vue Router and start to display different content based on the current URL. To do this, there is some HTML and JS modifications required. First, include the Vue router javascript file:

<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>script</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span><a class="token url-link" href="https://cdnjs.cloudflare.com/ajax/libs/vue-router/2.0.1/vue-router.js">https://cdnjs.cloudflare.com/ajax/libs/vue-router/2.0.1/vue-router.js</a><span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token script language-javascript"></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>script</span><span class="token punctuation">></span></span>

The next step is to replace our people-detail HTML component tag with one the router understands. Update the HTML view to the following:

<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>app<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>router-view</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>view<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>router-view</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span>

We now need to create a new VueRouter instance in the javascript. VueRouter accepts several arguments that need to be configured, but i’ll walk you though them:

<span class="token keyword">var</span> router <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">VueRouter</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
    mode<span class="token punctuation">:</span> <span class="token string">'hash'</span><span class="token punctuation">,</span>
    base<span class="token punctuation">:</span> window<span class="token punctuation">.</span>location<span class="token punctuation">.</span>href<span class="token punctuation">,</span>
    routes<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

The three options are:

  • mode - this set’s the navigation mode. The options can be:
    • history where it users HTML5 History API to simulate different page URLs
    • hash where it places a hash in the URL before each “page” or
    • abstract works in all JavaScript environments, e.g. server-side with Node.js
  • base - The base URL of your script (in this example i’ve used a javascript variable)
  • routes - this is where we will define each of our routes (URLs or pages)

For this app, I've chosen to use the hash mode for navigation. This means we can use the window.location.href variable as the base path. If we had use history we would need to use a .htaccess file or similar to direct all our paths to a single file.

Once set up, VueRouter instance needs to be passed into our main Vue object:

<span class="token keyword">var</span> app <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Vue</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
    router<span class="token punctuation">,</span>
    data<span class="token punctuation">:</span> <span class="token punctuation">{</span>
        <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">$mount</span><span class="token punctuation">(</span><span class="token string">'#app'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

Lastly, we need to slightly adjust our components to be assigned to variables, rather than creating HTML elements.

For example, replace the following Vue.component call

Vue<span class="token punctuation">.</span><span class="token function">component</span><span class="token punctuation">(</span><span class="token string">'people-listing'</span><span class="token punctuation">,</span> <span class="token punctuation">{</span>

with a new Vue.extend method

<span class="token keyword">var</span> PeopleListing <span class="token operator">=</span> Vue<span class="token punctuation">.</span><span class="token function">extend</span><span class="token punctuation">(</span><span class="token punctuation">{</span>

Our Vue app should now look like:

Which may seem “broken” as it’s now not outputting any data.

Create the routes

Routes are the different URLs the app uses to display different components. Each URL needs to be defined in the routes array - including the homepage. The routes we are going to use are as follows:

  • / - A single slash signifies the homepage of the app, this is going to display our PeopleListing component
  • /:id - The colon signifies the route is variable and will be replaced with the guid in our URL - this will display the PersonDetail component

Firstly, define the route for the landing page. With this, we are going to define the URL and the Vue component to display when viewing this URL:

If you are the following to your routes array:

routes<span class="token punctuation">:</span> <span class="token punctuation">[</span>
    <span class="token punctuation">{</span>path<span class="token punctuation">:</span> <span class="token string">'/'</span><span class="token punctuation">,</span> component<span class="token punctuation">:</span> PeopleListing<span class="token punctuation">}</span>
<span class="token punctuation">]</span>

You should see your listing view component appear when viewing the page. This is telling the router to show the PeopleListing component when on the / path.

Our second route is going to define the person detail view. As we are going to use the GUID dynamically for the URL, we need to name the route. - this will all become clear in a second. Our routes array now looks like:

routes<span class="token punctuation">:</span> <span class="token punctuation">[</span>
  <span class="token punctuation">{</span>path<span class="token punctuation">:</span> <span class="token string">'/'</span><span class="token punctuation">,</span> component<span class="token punctuation">:</span> PeopleListing<span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">{</span>name<span class="token punctuation">:</span> <span class="token string">'person'</span><span class="token punctuation">,</span> path<span class="token punctuation">:</span> <span class="token string">'/:id'</span><span class="token punctuation">,</span> component<span class="token punctuation">:</span> PersonDetail<span class="token punctuation">}</span>
<span class="token punctuation">]</span>

The second route now has a name of person and includes a dynamic variable in the path.

Any links using the router need to be constructed using the router-link element. More details can be found in the router-link documentation.

For example, to link to the landing/homepage you can include the following:

<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>router-link</span> <span class="token attr-name">to</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>/<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Homepage<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>router-link</span><span class="token punctuation">></span></span>

You can go ahead and add this to your people-detail-template.

We now need to add a link to our detail page in our listing component. Update the people-listing component to include the following router-link

<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>li</span> <span class="token attr-name">v-for</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>person in people<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    {{ person.name }} 
    <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>router-link</span> <span class="token attr-name">:to</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{ name: <span class="token punctuation">'</span>person<span class="token punctuation">'</span>, params: { id: person.guid }}<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>View Details<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>router-link</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>li</span><span class="token punctuation">></span></span>

You’ll notice because we are passing in dynamic data, the to attribute now has a : in front of it - this is shorthand for v-bind:to. You’ll also notice instead of specifying the URL, we call the name and pass the guid through as the id.

Now when you view your page and click one of the links, you’ll find it should (hopefully) navigate to #/{guid} where {guid} is a string.

The last step is displaying the correct data at this point. You can remove the fixed selectedID from the main Vue data object and in your PersonDetail component, replace the following in your if statement this.$parent.selectedID with the parameter from the URL: this.$route.params.id.

Success! You now have a web app which displays data and has shareable links for each person.

View it in action on JS Bin

If you view the bin in "output" mode, you'll notice the URL changing too:

Working Vue Router example

Let me know in the comments below if you have any problems or have a better way of using the Vue router on the client side.

You might also enjoy

  • Useful command line MySQL commands

    Posted on 5th July 2020.

    It seems I have been doing a lot of command line work on Debian with MySQL recently and have been having to search the internet (or my bash history) every time I need to do something. Here is a collection of commands I have been using…

  • The Git Commit Hash

    Posted on 28th May 2020.

    The magic 40 character string that is attached to every commit you do. What is it, where does it come from and will understanding it help you with Git in the future?…

  • Why should you consider Cloudflare for your website?

    Posted on 20th April 2020. Written For Liquid Light

    Cloudflare is a service which, among other things, provides a CDN (Content Delivery Network), firewall, and performance layer for your website. It has plenty of paid upgrades and features and is a developer’s dream, but what advantage does it have for you to put your website “behind” Cloudflare and how…

    Web
Mike Street

Written by Mike Street

Mike is a front-end developer from Brighton, UK. He spends his time writing, cycling and coding. You can find Mike on Twitter.