How to Use Vue Router

VueJS widespread library support is a key factor in its widespread adoption. One such package that works well with VueJS is Vue Router. Learn how VueJS development company connects Vue 3 to a Vue Router by reading this article. Let’s have a look at adding Vue Router to our Vue 3 project and see how to do it.

1. How to Use a Vue UI Router?

You can consider these steps for using a Vue router. 

1.1 Vue Router Installation

Vue Router is a routing library that establishes a connection between a path in the browser’s address bar or history and a specific view in Vue. The development of a Vue single-page application (SPA) requires the usage of a Vue router library.

The Vue.js framework does not provide a router component. The Vue-router package can be installed with the Vue CLI.

It’s accessible for npm installation:

npm  install vue-router

You may also utilize the CDN in conjunction with Vue CDN:

<script src="https://unpkg.com/vue@3"></script>
<script src="https://unpkg.com/vue-router@4"></script>

The router-link command may be used to add a route to your Vue component once the router has been installed.

<router-link to = "/route1">Link 1</router-link>
<router-link to = "/route2">Link 2</router-link>

Even though vue-router is already bundled with vue-cli, learning how to install it manually is a valuable skill.

Let’s get a basic vue-router demo up and running.

To include vue-router into our project, execute the following command.

npm install vue-router

Then, we inject the router into our Vue instance in the src/main.js file.

import Vue from 'vue'
import App from './App.vue'
import router from './router'// loads from src/router/index.js
 
new Vue({    
  router,
  render: h => h(App),
}).$mount('#app')
Make sure the following is stored in a file named index.js in the src/router folder.
import Vue from 'vue'
import VueRouter from  'vue-router'
import Dashboard from '../views/Dashboard.vue'
import AboutUs from '../views/AboutUs.vue'
Vue.use(VueRouter);
const routes = [
  {
    path: "/",
    name: "dashboard",
    component: Dashboard
  },
  {
    path: '/about-us',
    name: 'aboutUs',
    component: AboutUs
  }
]
const router = new VueRouter({
  mode: 'history',
  routes
})
export default router

We have finished configuring our vue-router, but there is now no way to access it.

The router-view element will help us do this. Vue-router needs a place to render the component that the existing URL points to, and that’s what the router-view component is for.

For demonstration purposes, we will place router-view in the App.vue root component. Let’s make some connections so we can easily switch between the two routes. vue-router utilizes router-link link elements with the to property that locate to a specific component.

<template>
  <div id="app">
    <router-link to='/'>Dashboard</router-link>
    <router-link to='/about-us'>About Us</router-link>
    <router-view  />
  </div>
</template>

When we launch our app, the dashboard component should be rendered. When we modify the router’s link components, both the text and the URL will shift.

1.2 Vue Router Fundamentals

Let’s start over with a new project. Vue-CLI will be used to initiate a brand-new project. Simply executing npm install -g @vue/cli will get it set up for you if you don’t already have it.

Establish a new Vue project.

vue create myapp
cd myapp

Simply executing this command will launch your application.

npm run serve

The following command will integrate the Vue Router into the current project.

vue add router
Vue Add Router

The CLI will inquire as to whether or not we want to use history mode. In this session, we will be using the history mode, thus we will choose this option.

Check out the pre-made folder structure we have here.

vue router folder structure

Two files, AboutUs.vue and Dashboard.vue, are placed in a folder we’ve given the name views. Our web pages are reflected in these files. In addition, a new file with the name router/index.js is created. All of the settings for the routers may be found in this file. The file router/index.js has to be opened.

import { createRouter, createWebHistory } from 'vue-router'
import Dashboard from '../views/Dashboard.vue'
const routes = [
  {
    path: '/',
    name: Dashboard',
    component: Dashboard
  },
  {
    path: '/about-us',
    name: 'AboutUs',
    // 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/AboutUs.vue')
  }
]
const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes
})
export default router

The Vue-router library’s createRouter and createWebHistory are being imported. We then bring in the views/Dashboard.vue dashboard component. On line 3, we’re making a declaration for a routes array. Our Vue application’s routes are represented by this array. We refer to the elements of this array as “route objects.” Since the first route object has the path /, this will serve as our starting point. This URL’s component attribute tells us which component to display when a user navigates to it. On this URL, we’ll display the homepage for you. The name property, which is the route’s actual name, rounds out the set.

For the most part, the /about route follows the same logic. Instead of including the component in our project directly, we’re using Webpack’s code splitting potential to bring it in. 

Let’s begin with the App.vue file right now.

<template>
  <div id="nav">
    <router-link to="/">Dashboard</router-link> |
    <router-link to="/about-us">About Us</router-link>
  </div>
  <router-view/>
</template>
<style>
</style>

Check the labels on the router links. These are only fancy forms of anchor text. Nevertheless, the router-link> will not force a full page refresh like an anchor link (a href=””> tag). Vue is a web program that only takes up one page. All of the necessary app data has been downloaded from the server. When we switch views, the software simply conceals unneeded data and presents the data you’ve asked for. A router-link tag can have a to property that specifies the URL address to go to. When a navigation link is clicked, the router-view/> tag is activated to display the appropriate component.

Create a new path for this program.

// App.vue
<template>
  <div id="nav">
    <router-link to="/">Dashboard</router-link> |
    <router-link to="/about-us">About Us</router-link>
    <router-link to="/contact">Contact</router-link>
  </div>
  <router-view/>
</template>

A new router-link must be added to App.vue. Then, we’ll make a new part in the views folder.

// views/Contact.vue
    <template>
      <div class="Dashboard">
        Contact Info
      </div>
    </template>

Finally, we need to import this into our routes array and set the path there.

import { createRouter, createWebHistory } from 'vue-router'
    import Dashboard from '../views/Dashboard.vue'
    import Contact from '../views/Contact.vue'
    const routes = [
      {
        path: '/',
        name: 'Dashboard',
        component: Dashboard
      },
      {
        path: '/contact',
        name: 'contact',
        component: Contact,
      },
      {
        path: '/about',
        name: 'About',
        // This is route level code-splitting
        // creates a separate chunk (about.[hash].js) for this route
        // and is lazy-loaded when the route is visited.
        component: () => import(/* webpackChunkName: "about" */ '../views/AboutUs.vue')
      }
    ]
const router = createRouter({
    routes,
      history: createWebHistory(process.env.BASE_URL)
    })
export default router

Finally, we have our own routes integrated into the system.

1.3 How to Use Router Params with Vue Router

Let’s start with a brief introduction of router parameters (or router params for short) and why they’re so crucial. Let’s assume our software has a page that lists all the blogs users may peruse.

In our program, perhaps this URL might be /posts. A person can access the article’s page by clicking on the article’s title. The URL structure will vary from article to article (/posts/article-1, /posts/article-2, etc.). How can we accomplish this? We can modify our code each time an additional article is published if we implement a new route for each post we have. So, we’ll take a more flexible path. The parameters for the router are useful in this situation.

A general route, such as /posts, may be specified in our application, and then additional route params, such as /posts/:id, can be specified. Any dynamic string can be used as a parameter in the:id. The Vue router in the app will recognize the intended destination path when it is given a string like /posts/article-1, /posts/article-2, etc.

Let’s put this into practice within our program.

// App.vue
<template>
  <div id="nav">
    <router-link to="/">Dashboard</router-link> |
    <router-link to="/about-us">About Us</router-link> |
    <router-link :to="{ name: 'contact', params: { username: 'mike' } }" >
      Contact
    </router-link>
  </div>
  <router-view/>
</template>

The :to property of the router-link tag allows us to provide an object with a title and parameters. Any data type (strings, integers, objects) is acceptable in the params object. In the aforementioned code snippet, username has a string value (mike) and is passed in as an object.

1.4 Nested Routes

The use of nested routes allows for the dynamic loading of individual modules. In addition, it works quite well with the Vue.js component architecture.

Take the case of displaying a message list on a website as an example. And when the user clicks on one of those messages, it should launch a private conversation.

We can build this functionality with a view and a component. So, we generated a new View named message in the views folder, and a new Component in the components folder that we named ChatRoom. Within the Message view, the ChatRoom component will be implemented.

The first step is to set up the route for the Message view in the application’s top-level navigation. My solution was to add a new route to the Message view by editing the App.vue and routes files.

//App.vue
<template>
  <div id="nav">
    <router-link to="/">Dashboard</router-link> |
    <router-link to="/our-messages">Our Message</router-link>
  </div>
  <router-view />
</template>
//router file
const routes = [
  {
    path: "/",
    name: "Dashboard",
    component: Dashboard,
  },
  {
    path: "/our-messages",
    name: "OurMessage",
    component: () =>
      import("../views/OurMessage.vue"),
  },
 ];

To replace the above route with a child route and load the child components, we have to add an additional <router-view> within the Message view. Once that is done, the altered files will look like this.

//Message.vue
<template>
  <div id="messagepage">
    <h1>Welcome to  messages page</h1>
    <div id="nav">
      <router-link to="/messages/chat/a">User A</router-link> |
      <router-link to="/messages/chat/b">User B</router-link> |
      <router-link to="/messages/chat/c">User C</router-link> |
      <router-link to="/messages/chat/d">User D</router-link>
    </div>
    <router-view />
  </div>
</template>
//router file
const routes = [
  {
    path: "/",
    name: "Dashboard",
    component: Dashboard,
  },
  {
    path: "/our-messages",
    name: "OurMessage",
    component: () =>
      import("../views/OurMessage.vue"),
    children: [
      { 
        path: 'chat/:userName',
        component: () =>
        import("../components/ChatRoom.vue"),
      }
    ]
  },
];

The routes taken by these offspring are only another array of routes that mirror the primary routing setup. A view component may have an unlimited number of child routes.

1.5 Dynamic Routes Matching

It is likely that we will have to assign the same component to many routes that have the specified pattern. Take the case of a User component that has to be rendered for all users, but with unique user IDs. Vue Router has a feature called a param that allows for a dynamic route segment to be used for this purpose.

js
const User = {
  template: '<div>User</div>',
}
 
// passed to `createRouter`
const routes = [
  // all dynamic segments start with a colon
  { path: '/user/:id', component: User },
]

There will be a single endpoint for URLs like /user/mike and /user/ross.

To indicate a parameter, use a colon:. The value of the route’s parameters will be revealed as this when the route is matched. Include $route.params in all of your modules. So, by making this change to User’s template, we can display the current user ID:

js
const User = {
  template: '<div>User {{ $route.params.id }}</div>',
}

1.6 Lazy Loading Routes

When using a bundler to construct an application, the resulting JavaScript bundle may grow in size and slow down page loads. Splitting apart the components of each route so that they are only loaded when the route is actually visited is more efficient.

Vue Router has built-in support for dynamic imports, allowing you to swap out static imports with their dynamic counterparts.

js
// replace
// import UserInfo from './views/UserInfo'
// with
const UserInfo = () => import('./views/UserInfo.vue')
 
const router = createRouter({
  // ...
  routes: [{ path: '/user/:id', component: UserInfo }],
})

If you select the component (and components) option, Vue Router will only fetch the component the first time you load the page and thereafter utilize the cached version. Therefore, more complicated functions are allowed, provided they return a Promise:

js
const UserInfo = () =>
  Promise.resolve({
    /* component definition */
  })

It’s recommended practice to employ dynamic imports in every route you create.

Note

  • Do not build your routes with Async components. Route components are only dynamic imports, therefore async components may still be used within them.
  • Code splitting is an inherent part of utilizing a bundler like webpack for this.
  • In order for Babel to correctly parse the syntax, the syntax-dynamic-import plugin must be installed.

1.7 Programmatic Navigation

There will be situations in our programs in which we are going to want to navigate programmatically to a different page. $router provides permissions for the router instance within our app’s code. This can be accessed by invoking **this.$router**. The router instance has a send function. This function enables navigation to various itineraries. Here are a few examples of the way it operates.

// route by route path
this.$router.push(dashboard')
 
// object
this.$router.push({ path: 'dashboard' })
 
// named route navigation with parameters
this.$router.push({ name: 'user', params: { userName: 'mike' } })
 
// with query params, resulting in /contact?info=some-info
this.$router.push({ path: 'contact', query: { info: 'some-info' } })

1.8 Access the Route Parameters

We’ve seen how to dynamically transmit parameters to a specific page; now let’s see how to reach that parameter in our FruitInfo page. Vue provides two methods for gaining access to parameters: $route.params and props.

  • Using $route.params

The parameters can be accessed directly via $route.params:

<template>
   <h1>Fruit Info</h1>
   <p>The id of fruit is  {{ $route.params.id }}</p>
</template>

Also, we can access it through data() method:

<template>
   <h1>Fruit Info</h1>
   <p>The id of fruit is {{ id }}</p>
</template>
 
<script>
   export default {
      data() {
         return {
            id: this.$route.params.id,
         };
      },
   };
</script>
  • Using Vue Props

Using properties is another simple way to access data dynamically via routes. The routes configuration object requires you to set the props property to true.

{
   path: '/fruit/:id',
   name: 'FruitInfo',
   component: FruitInfo,
   props: true,
},

Thus, all that remains is to apply the props option to the script tag and utilize the props within our template tag.

<template>
   <h1>Fruit Info</h1>
   <p>The id of fruit is {{ id }}</p>
</template>
 
<script>
   export default {
      props: ['id'],
   };
</script>

1.9 Vue Router Using Composition API

The addition of setup and Vue’s Composition API creates new opportunities, but to get the most out of Vue Router, we must substitute existing access to this and in-component navigation protections with a few new functions.

  • Accessing the Router and Current Route within the configuration

Since we no longer have entry to this within the setup, we no longer have immediate access to this.$router or this.$route. Use the useRouter and useRoute functions instead:

js
import { useRouter, useRoute } from 'vue-router'
 
export default {
  setup() {
    const myRouter = useRouter()
    const myRoute = useRoute()
 
    function pushWithQuery(query) {
      myRouter.push({
        name: 'search',
        query: {
          ...myRoute.query,
          ...query,
        },
      })
    }
  },
}

The myRoute object is a reactive object; therefore, any of its properties can be monitored, and the myRoute object as a whole should not be monitored. In the majority of cases, you should explicitly monitor the parameter you intend to alter.

js
import { useRoute } from 'vue-router'
import { ref, watch } from 'vue'
 
export default {
  setup() {
    const myRoute = useRoute()
    const userInfo = ref()
 
    // get user information on param change
    watch(
      () => myRoute.params.id,
      async newId => {
        userInfo.value = await getUser(newId)
      }
    )
  },
}

Remember that $router and $route may still be used in template files, thus there’s no reason to return them in setup.

  • Navigation Guards​

Vue Router offers the update and leave guards as Composition API methods, but it still allows in-component navigation guards with a setup function.

Js
import { ref } from 'vue'
import { onBeforeRouteLeave, onBeforeRouteUpdate } from 'vue-router'
 
export default {
  setup() {
    // same as beforeRouteLeave but with no access to `this`
    onBeforeRouteLeave((to, from) => {
      const response = window.confirm(
        'Are you sure you want to leave? You have got unsaved changes!'
      )
      // cancel navigation and stay on the current page
      if (!response) return false
    })
 
    const userInfo = ref()
 
    // same as beforeRouteUpdate but with no access to `this`
    onBeforeRouteUpdate(async (to, from) => {
      // get the user only if the id changes as maybe only the query or the hash changes
      if (to.params.id !== from.params.id) {
        userInfo.value = await getUser(to.params.id)
      }
    })
  },
}

Unlike in-component guards, which must be placed explicitly on the route component, composition API guards can be placed everywhere a <router-view> component is displayed.

Vue Router makes available a composable RouterLink’s internal behavior. It accepts a reactive object similar to RouterLink’s attributes and exposes low-level properties for constructing a custom RouterLink component or generating custom links:

js
import { computed } from 'vue'
import { RouterLink, useLink } from 'vue-router'
 
 
export default {
  name: 'AppLink',
 
  props: {
    // add @ts-ignore if using TypeScript
    ...RouterLink.props,
    inactiveClass: String,
  },
 
  setup(props) {
    const {
      // resolved route object
      route,
      // href to use in a link
      href,
      // boolean  indicating if the link is active
      isActive,
      // boolean  indicating if the link is exactly active
      isExactActive,
      // function to navigate to link
      navigate
      } = useLink(props)
 
    const isLinkExternal = computed(
      () => typeof props.to === 'string' && props.to.startsWith('http')
    )
 
    return { href, isActive, navigate, isLinkExternal}
  },
}

Note that the RouterLink v-slot provides access to identical properties as the useLink composable.

1.10 Handling 404 Errors

Let’s consider a user who goes to a page that wasn’t included in our router’s initial configuration file. There is a missing component, but our Vue app will still launch. There must be a means to instruct the router on what to do in this situation.

Adding the following code to our index.js file will update our router setup to support this functionality.

{
        path: "/:catchAll(.*)",
        component: () => import(
        /* webpackChunkName: "PathNotFound" */ '../views/PathNotFound.vue')
    },

To do this, Vue Router employs a specialized regular expression. :catchAll is for checking to see if a certain route is defined in our router’s configuration file, Vue Router employs a regular expression consisting of the dynamic segment all and the wildcard character (.*). In the event that it cannot be found, our PathNotFound.vue component will be displayed.

2. Conclusion

In web development, routing is a system through which HTTP requests are sent to the appropriate pieces of code. A router allows you to specify the actions to take when a user navigates to a specific page.

With the advent of JavaScript frameworks, web routing has evolved and become less difficult to build.

Vue’s routing functionality is managed via the Vue Router package. Vue Router is a must-have if your Vue-based web app or website has numerous pages that visitors will need to navigate between.

3. FAQs

What is the Alternative to Vue router?

Some of the major alternatives of Vue Router are React Router, Angular CLI, Nuxt.js, Storybook, and Axios.

What is the Difference Between Vue Router and Express Router?

Vue router enables the developers to create Single Page Apps (SPA) with client-side rendered content. With the help of it users can switch between pages without any requirement to reload the page which eventually offers a seamless transition. On the other hand, the Express route allows application content to be rendered on the server side. And it helps in creating a new router object in the program to handle requests.

What is the Purpose of Vue Router?

The main purpose of Vue Router is to navigate the application on the client side without reloading the entire webpage resulting in faster user experience.

Does Vue Router Use History or Hash?

By default, the Vue router is in hash mode. This means Vue router uses the URL to simulate it so that the web page doesn’t get reloaded when there are URL changes.

profile-image
Itesh Sharma

Itesh Sharma is core member of Sales Department at TatvaSoft. He has got more than 6 years of experience in handling the task related to Customer Management and Project Management. Apart from his profession he also has keen interest in sharing the insight on different methodologies of software development.

Comments

  • Leave a message...