You can define nested routes in Vue.js (using vue-router) by chaining each of the routes on the root route. For instance, if there’s a route named user/gautam, you can nest the child routes dynamically as user/gautam/photos, user/gautam/profile, etc.
For this to work correctly, make sure you have compatible version of the vue-router installed for your Vue.js version. Here are my package versions:
- @vue/cli-plugin-babel (4.1.1)
- vue (2.6.11)
- vue-router (3.2)
Now, I’ll create four small components, for each of the following route:
- Root: This route will have a component displayed at all times (root route)
- Home
- Profile
- Photos
These are the file content for each of the components:
//UserHome.vue
<template>
<div>
<div>User Home</div>
</div>
</template>
<script>
export default {
name: "UserHome",
};
</script>
Code language: HTML, XML (xml)
//UserPhotos.vue
<template>
<div>
<div>User Photos</div>
</div>
</template>
<script>
export default {
name: "UserPhotos",
};
</script>
Code language: HTML, XML (xml)
//UserProfile.vue
<template>
<div>
<div>User Profile</div>
</div>
</template>
<script>
export default {
name: "UserProfile",
};
</script>
Code language: HTML, XML (xml)
//UserRoot.vue
<template>
<div class="user-root">
<p>User: {{ $route.params.user.toUpperCase() }}</p>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: "UserRoot",
};
</script>
<style>
.user-root {
border: 1px solid rgb(0, 119, 255);
margin: 20px 0;
padding: 10px;
}
</style>
Code language: HTML, XML (xml)
Please note that in the above file, there’s a router-view slot (line 6), it means that all the matched route components will be shown at this place. That is, right under User: Gautam.
And here’s my App.vue file to show links to each of the routes:
<template>
<div id="app">
<div>
<div class="router-link">
<router-link to="/user/gautam">User</router-link>
</div>
<div class="router-link">
<router-link to="/user/gautam/profile">User Profile</router-link>
</div>
<div class="router-link">
<router-link to="/user/gautam/photos">User Photos</router-link>
</div>
</div>
<router-view></router-view>
<div class="np-credits">wwww.nightprogrammer.com</div>
</div>
</template>
<script>
export default {
name: "App",
};
</script>
<style>
#app {
font-family: "Avenir", Helvetica, Arial, sans-serif;
padding: 24px;
}
.np-credits {
font-size: 12px;
margin-top: 12px;
color: #4b4b4b;
}
.router-link {
display: inline-block;
margin-right: 10px;
font-size: 14px;
}
.router-link a {
text-decoration: none;
font-weight: 600;
color: rgb(0, 60, 255) !important;
}
.router-link a:active {
color: rgb(255, 0, 0) !important;
}
</style>
Code language: HTML, XML (xml)
The above file will generate the following view:
And finally, here’s my main.js file, combing all these files together:
import Vue from "vue";
import App from "./App.vue";
import VueRouter from "vue-router";
import UserRoot from "./UserRoot";
import UserHome from "./UserHome";
import UserProfile from "./UserProfile";
import UserPhotos from "./UserPhotos";
Vue.config.productionTip = false;
const routes = [
{
path: "/user/:user",
component: UserRoot,
children: [
{ path: "", component: UserHome },
{ path: "profile", component: UserProfile },
{ path: "photos", component: UserPhotos }
]
}
];
Vue.use(VueRouter);
const router = new VueRouter({
routes
});
new Vue({
render: (h) => h(App),
router
}).$mount("#app");
Code language: JavaScript (javascript)
In the above file, I’ve imported each of the component files at the top. I’ve registered the root path as /user/:user on line 13. I’ve used the UserRoot component for the path. It means that, this component will be shown at all times.
Then in the children prop, I’ve defined paths for the child components, named UserHome, UserProfile and UserPhotos for /user/gautam, /user/gautam/profile and /user/gautam/photos respectively. This is how the above code will look like in action: