Introducing routing to our app

Most apps as they grow need to support routing. Routing in the context of frameworks is the binding of components to URLs so that when a request comes in for a URL such as /about, an About component is rendered into the view. Vue has an entire library dedicated to routing and we'll explore it now.

Learning Objectives

How Vue routing works

Vue's router works by creating a new instance of the Vue router and passing in an array of routes.

Add the following into main.js:

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

We then need to pass our new router object into our app component like so:

var app = new Vue({
  router,
  el: '#app',

  // other elements omitted

You'll notice we only support one route for now, which is the index route. This route is configured to render the Home component.

Re-imagining our app

When using the Vue router, we render components inside a router-view tag. Since we don't want the home page content to render on other pages, this raises the question: how do we render the current content on the home page into the router view?

One solution is to introduce a Home component. This component will be responsible for the main home page content and will render the three products that are currently rendered from the index.html file.

Remove the home content from index.html and add it into a Home component in your main.js file. You should end up with something like this:

const Home = Vue.component('Home', {
  template: `
    <div>
      <h2>Popular plants</h2>
      <p>
        Want to "fernish" your home? Then you're in the right place! Take a
        look at our selection of plants below.
      </p>
      <div class="promo-blocks products">
        <product
          v-for="product in products"
          v-bind:key="product.productId"
          v-bind:product="product"
          v-on:add-to-cart="updateCart"
        ></product>
      </div>
    </div>
  `,
});

Replace the content you removed in the index.html file with router-view tags. You should end up with something like this:

<main>
  <div class="container">
    <router-view />
  </div>
</main>

This cleans up on HTML source nicely. If you refresh your page now, it should work, however, the products aren't rendering. This is because the Home component has no concept of the Products at this point in time. We have to pass the products as a prop if it is to work.

Modify your router tag to:

<router-view v-bind:products="this.products" />

Given what we've covered so far, you may be able to see and explain what's going on here!

The last thing we need to do is tell the Home component to expect a property called products. To do that, you may remember we need to add a props field to the Home component:

const Home = Vue.component('Home', {
  template: `
    HTML omitted
  `,
  props: ['products'], // add this line
  methods: {
    // methods omitted
  },
});

Now when you refresh your page, your Home component will be able to "see" the products passed down as props via the router view.

The last step is to replace our main menu with router-links ready for the coding challenge. Vue will find and replace router links with anchor tags so we can navigate between pages. Replace the main menu links in index.html with:

<ul class="navbar__navigation">
  <li><router-link to="/">Home</router-link></li>
  <li><router-link to="/about">About</router-link></li>
  <li><router-link to="/contact">Contact</router-link></li>
</ul>

Assignment - Coding challenge

Part one

You'll notice that the new router links actually work, but no component is rendered on a click. Your coding challenge is to create two new routes for /about and /contact and two new components About and Contact that are loaded into the router view when requested.

Part two

Add some basic markup/content to your About and Contact pages for stakeholder review!

Additional resources