Banner
Home / Blog / Creating Your Own Vue.js Router
Creating Your Own Vue.js Router

Creating Your Own Vue.js Router

Alex Jover Morales
Alex Jover Morales
January 26th 2018
This entry is part 1 of 4 in the series Creating Your Own Router

Probably you've been using routers in the frontend world for a while, but... have you ever written one by yourself? Do you know the foundations of a router? It might seem like it just works, but under the hood a router must take care of several things.

A router is the component in charge of routing. We can define routing as the action of finding the way to multiple destinations. This applies to different areas.

For instance an elevator’s router will take you to the fifth floor if you press the button with the number 5 on it.

In web development, we can see two main areas of routing:

  • Back-end: the router calls the right controller, matching a url pattern.
  • Front-end: the router loads the corresponding component into the view, matching a url pattern.

In this series we’ll look at how we can create our own front-end router with Vue.js, in order to understand the mechanics of a router.

Create A Basic Router Component

Let's first create the components Home and Articles to use for the routes. The content is not important since is just for showing something on that route, something like the following is enough:

<!-- Home.vue -->
<template>
  <div>Home</div>
</template>

<!-- Articles.vue -->
<template>
  <div>Articles</div>
</template>

Since Vue.js is a component based framework, a simple way to create a router is by using a component. That way is more universal, since any front-end developer that has worked on any component based tool would be able to understand it.

Define the routes

Let’s start by creating a AppRouter.vue file which will be the Router component itself, with the definition of the routes:

<!-- Router.vue -->
<script>
import HomePage from "./HomePage";
import ArticlesPage from "./ArticlesPage";

const routes = {
  "/": HomePage,
  "/articles": ArticlesPage
};
</script>

I'm importing both HomePage and ArticlesPage components and creating a routes object, which keys are the route path and the value is the component itself. Accessing the route in this way is simple and fast, since accessing an object property is a direct operation, just by doing routes["/"].

If you need more customisation, other ways to define them would be using an object as the value:

const routes = {
  "/": {
    component: HomePage,
    default: true, // indicate if it's the default route
    name: "root"
  }
}

You could do it using an array as well, just as vue-router does. The array solution is more flexible while more complicated, since you’ll need later to loop through:

const routes = [
  {
    path: "/"
    component: HomePage
  }
}

// A simple way to get the component is using ES2015 array find method
const route = routes.find(route => route.path === "/");

Render the Router component
Once we have the routes set up, we need a way to render a component given a condition. Vue.js template provide us with dynamic components, which are perfect for our case.

A dynamic component allow us to easily hot-swap between components by using the special <component> element, by using an is property as a condition:

<template>
  <component :is="routedComponent"></component>
</template>

Then we need to implement that condition. Since that condition will change depending on the route, a computed property fits perfectly for the purpose:

export default {
  data() {
    return { current: window.location.pathname };
  },
  computed: {
    routedComponent() {
      return routes[this.current];
    }
  }
};

The computed property would be a good place to return a component for a default route (a route that doesn't matches any), and it would be as easy as using an OR operator:

routedComponent() {
  return routes[this.current] || DefaultComponent;
}

The final Router.vue component is:

<!-- Router.vue -->
<template>
  <component :is="routedComponent"></component>
</template>

<script>
import HomePage from "./HomePage";
import ArticlesPage from "./ArticlesPage";

const routes = {
  "/": HomePage,
  "/articles": ArticlesPage
};

export default {
  data() {
    return { current: window.location.pathname };
  },
  computed: {
    routedComponent() {
      return routes[this.current];
    }
  }
};
</script>

As an alternative solution, render functions (or JSX) fits perfectly for this case, since rendering with render functions is dynamic by default. So you could rewrite the component in a Router.js file:

// Router.js
import HomePage from "./HomePage";
import ArticlesPage from "./ArticlesPage";

const routes = {
  "/": HomePage,
  "/articles": ArticlesPage
};

export default {
  data() {
    return { current: window.location.pathname };
  },
  computed: {
    routedComponent() {
      return routes[this.current];
    }
  },
  render(createElement) {
    return createElement(this.routedComponent);
  }
};

Using The Router Component

Let's create an App.vue component as the root component for the application. Then import and register the router component:

<!-- App.vue -->
<template>
  <div>
    <app-router></app-router>
  </div>
</template>

<script>
import AppRouter from "./AppRouter";

export default {
  components: {
    AppRouter
  }
};
</script>

In the template, we place the <app-router> tag which will be replaced by the component rendered by the router. In the script section, the Router is imported and added to the App component.

If you run the app and navigate between / and /articles by writing the routes in your browser's bar, you should see the router loads the corresponding component and its content.

To make it more convenient, let's add a couple of buttons and a method to navigate between routes in App.vue:

<!-- App.vue -->
<template>
  <div>
    <button @click="goTo('/articles')">Go to Articles</button>
    <button @click="goTo('/')">Go to Home</button>
    <app-router></app-router>
  </div>
</template>

<script>
import AppRouter from "./AppRouter";

export default {
  components: {
    AppRouter
  },
  methods: {
    goTo(route) {
      window.location = route;
    }
  }
};
</script>

Try it again and click on the buttons, it should still work the same way.
Find here the code and demo from this article and try it yourself!

Start learning Vue.js for free

Alex Jover Morales
Alex Jover Morales
Passionate web developer. Author of Test Vue.js components with Jest on Leanpub. I co-organize Alicante Frontend. Interested in web performance, PWA, the human side of code and wellness. Cat lover, sports practitioner and good friend of his friends. His bike goes with him.

Latest Vue School Articles

Crafting a Custom Component Library with Vue and Daisy UI

Crafting a Custom Component Library with Vue and Daisy UI

Do you want to build your own component library with Vue.js? We’ll show you how to get started in our course: Crafting a Custom Component Library with Vue and Daisy UI.
Daniel Kelly
Daniel Kelly
What Makes a Good (Vue) Component Library? A Checklist

What Makes a Good (Vue) Component Library? A Checklist

Considering building a Vue Component library? Checkout this checklist of concerns you should make sure to remember!
Daniel Kelly
Daniel Kelly

Our goal is to be the number one source of Vue.js knowledge for all skill levels. We offer the knowledge of our industry leaders through awesome video courses for a ridiculously low price.

More than 120.000 users have already joined us. You are welcome too!

Follow us on Social

© All rights reserved. Made with ❤️ by BitterBrains, Inc.