Vue Router example – with Nav Bar, Dynamic Route & Nested Routes

vue-router-example-feature-image

Vue Router example – with Nav Bar, Dynamic Route & Nested Routes

Vue Router deeply integrates with Vue.js that we can use to build single-page Vue Application in simple way. In this tutorial, we’re gonna look at a Vue Router example that allows us to navigate among tabs and dynamically show item details from a item list with Nav bar, Dynamic Route and Nested Routes.

More Practice:
Spring Boot + Vue.js example | Spring Data JPA + REST + PostgreSQL CRUD
Spring Boot + Vue.js example | Spring Data JPA + REST + MySQL CRUD

Vue Router example Overview

Goal

vue-router-example-nav-bar-dynamic-route-nested-routes-result

We can:
– click on Nav Bar button to change view among Pages.
– click on any Customer to show details.

Demo

Vue Router

When adding Vue Router to Vue App, we have 2 core actions:
– map components to the routes
– let Vue Router know where to render them

Add Vue Router to Project

– Run command: npm install vue-router.
– Import router to main.js:

import Vue from "vue";
import App from "./App.vue";
import router from './router'

Vue.config.productionTip = false;

new Vue({
  router, // inject the router to make whole app router-aware
  render: h => h(App)
}).$mount("#app");

Vue Router with Nav Bar

– Define some routes, each route has a path and maps to a component:
src/router.js

import Vue from "vue";
import Router from "vue-router";
import CustomersList from "./components/CustomersList.vue";
import AddCustomer from "./components/AddCustomer.vue";
import SearchCustomers from "./components/SearchCustomers.vue";

Vue.use(Router);

export default new Router({
  // get rid of the hash (#) in Url
  // the hash (#) helps the page not to be reloaded when the URL changes
  mode: "history",
  routes: [
    {
      path: "/",
      name: "customers",
      alias: "/customer", // go '/', the URL remains '/', but it wcill be matched if visiting '/customer'
      component: CustomersList
    },
    {
      path: "/add",
      name: "add",
      component: AddCustomer
    },
    {
      path: "/search",
      name: "search",
      component: SearchCustomers
    }
  ]
});

src/App.vue

<template>
    <div id="app">
        <nav>
            <router-link to="/">Customers</router-link>
            <router-link to="/add">Add</router-link>
            <router-link to="/search">Search</router-link>
        </nav>
        <router-view/>
    </div>
</template>

– We use router-link component for navigation and specify the link with ‘to’ prop. By default, <router-link> will be rendered as an <a> tag.
router-view is the router outlet that render the matched component.

Vue Router with Dynamic Route

For mapping routes with the given pattern to the same component:
With path: "/customer/:id", urls like /customer/1 and /customer/42 will both map to the same route:
router.js

const router = new VueRouter({
  routes: [
    { 
      path: "/customer/:id",
      name: "customer-details",
      component: Customer
    }
  ]
});

When a route is matched, the value of the dynamic segments will be exposed as this.$route.params in every component. Therefore, we can render the current id with this.$route.params.id:
Customer.vue

<template>
    <div>
        [id: {{ this.$route.params.id }} - 
        name: {{ this.$route.params.name }}]
    </div>
</template>

<script>
export default {
  name: "customer"
};
</script>

Vue Router with Nested Routes

To render components into another one, we need to use the children option in Vue Router constructor config:
router.js

export default new Router({
    routes: [
        {
            path: "/",
            name: "customers",
            component: CustomersList,
            children: [
                {
                    path: "/customer/:id",
                    name: "customer-details",
                    component: Customer
                }
            ]
        }
    ]
});

Then add the child component inside the parent component’s template:
CustomersList.vue

<template>
    <div>
        <ul>
            <li v-for="(customer, index) in customers" :key="index">
                <router-link :to="{name: 'customer-details', params: { name: customer.name, id: index + 1 }}">
                    {{customer.name}}
                </router-link>
            </li>
        </ul>
        <router-view></router-view>
    </div>
</template>

We use Named Route name: 'customer-details' to make link to component, and we can also pass an object ({name, id}) to the router-link component:

Customer ABC

Project Structure

vue-router-example-nav-bar-dynamic-route-nested-routes-project-structure

We have:
– Components: CustomersList, AddCustomer, SearchCustomers are corresponding to 3 Navbar buttons: Customers, Add, Search.
Customer components is the child of CustomersList component, its UI view is embeded into parent component using <router-view> tag.
App.vue contains the whole application template with Nav bar and <router-view>.
– We define routes, each route has a path and maps to a component in router.js.
main.js mount App component with router to be injected.

Practice

Technologies

– Vue CLI 3.0.1
– Vue 2.5.17
– Vue Router 3.0.1

Setup Vue Project

Install vue-cli

For use Vue CLI anywhere, run command:
npm install -g vue-cli

Init Project

Point cmd to the folder you want to save Project folder, run command:
npm create vue-router-example

You will see 2 options, choose default:

vue-create-project-config

Add Vue Router to Project

– Run command: npm install vue-router.
– Import router to main.js:

import Vue from "vue";
import App from "./App.vue";
import router from './router'

Vue.config.productionTip = false;

new Vue({
  router, // inject the router to make whole app router-aware
  render: h => h(App)
}).$mount("#app");

Define Routes

src/router.js:

import Vue from "vue";
import Router from "vue-router";
import CustomersList from "./components/CustomersList.vue";
import AddCustomer from "./components/AddCustomer.vue";
import SearchCustomers from "./components/SearchCustomers.vue";
import Customer from "./components/Customer.vue";

Vue.use(Router);

export default new Router({
  mode: "history",
  routes: [
    {
      path: "/",
      name: "customers",
      alias: "/customer",
      component: CustomersList,
      children: [
        {
          path: "/customer/:id",
          name: "customer-details",
          component: Customer
        }
      ]
    },
    {
      path: "/add",
      name: "add",
      component: AddCustomer
    },
    {
      path: "/search",
      name: "search",
      component: SearchCustomers
    }
  ]
});

App template with Navbar and router-view

src/App.vue:

<template>
    <div id="app" class="container-fluid">
        <div class="site-info">
            <h1>ozenero</h1>
            <h3>Router example</h3>
        </div>
        <nav>
            <router-link class="btn btn-primary" to="/">Customers</router-link>
            <router-link class="btn btn-primary" to="/add">Add</router-link>
            <router-link class="btn btn-primary" to="/search">Search</router-link>
        </nav>
        <br/>
        <router-view/>
    </div>
</template>

<script>
export default {
  name: "app"
};
</script>

<style>
.site-info {
  color: blue;
  margin-bottom: 20px;
}

.btn-primary {
  margin-right: 5px;
}

.container-fluid {
  text-align: center;
}
</style>

Mock Components

components/AddCustomer.vue:

<template>
  <div>
    <h4>Add Customer page</h4>
    <p>[under construction...]</p>
  </div>
</template>
</pre>
<em>components/SearchCustomers.vue</em>:
<pre class="lang:xhtml">
<template>
  <div>
    <h4>Search Customers Page</h4>
    <p>[under construction...]</p>
  </div>
</template>

Components with Dynamic Route & Nested Routes

Parent Component

components/CustomersList.vue:

<template>
    <div class="list row">
        <div class="col-md-6">
            <h4>Customers List</h4>
            <ul>
                <li v-for="(customer, index) in customers" :key="index">
                    <router-link :to="{
                            name: 'customer-details',
                            params: { name: customer.name, id: index + 1 }
                        }">
                            {{customer.name}}
                    </router-link>
                </li>
            </ul>
        </div>
        <div class="col-md-6">
            <router-view></router-view>
        </div>
    </div>
</template>

<script>
export default {
  name: "customers-list",
  data() {
    return {
      customers: [
        { name: "Jack Smith" },
        { name: "Adam Johnson" },
        { name: "Katherin Watson" }
      ]
    };
  }
};
</script>

<style>
.list {
  text-align: left;
  max-width: 500px;
  margin: auto;
}
</style>

Child Component

components/CustomersList.vue:

<template>
    <div v-if="this.$route.params.name">
        <h4>Customer</h4>
        [id: {{ this.$route.params.id }} - 
        name: {{ this.$route.params.name }}]
    </div>
    <div v-else>
        <br/>
        <p>Please click on a Customer...</p>
    </div>
</template>

<script>
export default {
  name: "customer"
};
</script>

Source Code

vue-router-example

0 0 votes
Article Rating
Subscribe
Notify of
guest
636 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments