Nested Routes

Watch a free video lesson on Vue School

Some application’s UIs are composed of components that are nested multiple levels deep. In this case, it is very common that the segments of a URL corresponds to a certain structure of nested components, for example:

  1. /user/johnny/profile /user/johnny/posts
  2. +------------------+ +-----------------+
  3. | User | | User |
  4. | +--------------+ | | +-------------+ |
  5. | | Profile | | +------------> | | Posts | |
  6. | | | | | | | |
  7. | +--------------+ | | +-------------+ |
  8. +------------------+ +-----------------+

With Vue Router, you can express this relationship using nested route configurations.

Given the app we created in the last chapter:

  1. <div id="app">
  2. <router-view></router-view>
  3. </div>
  1. const User = {
  2. template: '<div>User {{ $route.params.id }}</div>',
  3. }
  4. // these are passed to `createRouter`
  5. const routes = [{ path: '/user/:id', component: User }]

The <router-view> here is a top-level router-view. It renders the component matched by a top level route. Similarly, a rendered component can also contain its own, nested <router-view>. For example, if we add one inside the User component’s template:

  1. const User = {
  2. template: `
  3. <div class="user">
  4. <h2>User {{ $route.params.id }}</h2>
  5. <router-view></router-view>
  6. </div>
  7. `,
  8. }

To render components into this nested router-view, we need to use the children option in any of the routes:

  1. const routes = [
  2. {
  3. path: '/user/:id',
  4. component: User,
  5. children: [
  6. {
  7. // UserProfile will be rendered inside User's <router-view>
  8. // when /user/:id/profile is matched
  9. path: 'profile',
  10. component: UserProfile,
  11. },
  12. {
  13. // UserPosts will be rendered inside User's <router-view>
  14. // when /user/:id/posts is matched
  15. path: 'posts',
  16. component: UserPosts,
  17. },
  18. ],
  19. },
  20. ]

Note that nested paths that start with / will be treated as a root path. This allows you to leverage the component nesting without having to use a nested URL.

As you can see the children option is just another Array of routes like routes itself. Therefore, you can keep nesting views as much as you need.

At this point, with the above configuration, when you visit /user/eduardo, nothing will be rendered inside User‘s router-view, because no nested route is matched. Maybe you do want to render something there. In such case you can provide an empty nested path:

  1. const routes = [
  2. {
  3. path: '/user/:id',
  4. component: User,
  5. children: [
  6. // UserHome will be rendered inside User's <router-view>
  7. // when /user/:id is matched
  8. { path: '', component: UserHome },
  9. // ...other sub routes
  10. ],
  11. },
  12. ]

A working demo of this example can be found here.