| |

Vue.js 57 🟢 Nested Routes, Named Views, and Route Aliasing

⏱️ Estimated read: 13 min | |

A Vue application’s UI is rarely a single flat layer. A dashboard has a persistent sidebar and a main content area. A settings page has a navigation panel and a detail pane. A user profile has a header that stays while the tab content changes. Vue Router expresses these structures through three distinct mechanisms: nested routes for components inside components, named views for multiple sibling components at the same level, and aliases for making one route reachable through multiple URLs without redirecting.

The distinction between nested routes and named views is the one that trips people up. Nested routes are about hierarchy: a parent component contains a <router-view>, and the child route’s component renders inside that parent. Named views are about parallelism: a single route renders multiple components into multiple <router-view> outlets that sit side by side, not inside each other . Aliases are about identity: a route has a canonical path, and an alias makes a second path behave exactly like the first without changing the URL the user sees .

Key point: Nested routes use the children array and render inside a parent component’s <router-view>; named views use the components object (plural) and render into multiple sibling <router-view> outlets identified by name; aliases use the alias property and map an additional path to the same route record without redirecting the user.


Why nested routes, named views, and aliases exist

The layout composition problem. A settings page like /settings/profile and /settings/emails share the same navigation sidebar but display different content in the main area. The sidebar is not part of the profile component or the emails component—it is part of the parent layout. Nested routes solve this by making UserSettings the parent component that contains the sidebar and a <router-view>, and the child routes render into that <router-view> . The parent stays mounted while the child changes.

The parallel outlet problem. A layout might need three independent regions: a sidebar, a main content area, and a footer, each rendering a different component for the same route. Nested routes cannot express this because they only provide one nested outlet per parent. Named views solve it by giving each <router-view> a name and mapping each name to a component in the route’s components object . The route renders all three components simultaneously, side by side.

The canonical URL problem. A route like /users/42/profile might also be reachable as /profile/42 for legacy reasons, or /u/42/profile as a shorthand. A redirect changes the URL and triggers a new navigation. An alias keeps the URL the user typed but matches it as if they had visited the canonical path . The component renders without the URL changing, which matters for user experience and for preserving the original link.

The path nesting problem. Not every nested route needs a nested URL. A parent route might exist only to provide a component wrapper or a navigation guard, and its children might have absolute paths that start with /. Vue Router treats paths starting with / inside children as root paths, which means the component nesting is preserved but the URL is not . This is useful when the visual hierarchy and the URL hierarchy should not match.


a. Nested routes: components inside components

A nested route is defined with the children array on a parent route. The parent component must contain a <router-view> where the child renders.

// router.js
import { createRouter, createWebHistory } from 'vue-router'
import User from './User.vue'
import UserProfile from './UserProfile.vue'
import UserPosts from './UserPosts.vue'
import UserHome from './UserHome.vue'

const router = createRouter({
  history: createWebHistory(),
  routes: [
    {
      // Parent route: /user/:id
      path: '/user/:id',
      component: User,
      children: [
        // Empty path renders UserHome at /user/:id
        { path: '', component: UserHome },
        // Renders inside User's <router-view> at /user/:id/profile
        { path: 'profile', component: UserProfile },
        // Renders inside User's <router-view> at /user/:id/posts
        { path: 'posts', component: UserPosts },
      ],
    },
  ],
})

The parent component User.vue must have its own <router-view>. Without it, the child route matches but nothing renders.

<!-- User.vue -->
<template>
  <div class="user">
    <!-- The :id param is available from the parent route -->
    <h2>User {{ $route.params.id }}</h2>
    <!-- Child routes render here -->
    <router-view />
  </div>
</template>

The empty path '' is the default child route. When the URL is exactly /user/42 and no further segment is present, the UserHome component renders inside User‘s outlet . Without it, visiting /user/42 would render the parent component with an empty outlet, which is usually not what the user expects.

A nested path that starts with / is treated as a root path. The component nesting is preserved—it still renders inside the parent’s <router-view>—but the URL does not include the parent segment. This is useful for grouping routes under a layout without reflecting the layout in the URL .


b. Named views: multiple outlets at the same level

Named views are defined with the components object on a single route. Each key in the object matches a name attribute on a <router-view> in the template.

<!-- App.vue -->
<template>
  <div class="layout">
    <!-- Renders the component mapped to "sidebar" -->
    <router-view name="sidebar" class="sidebar" />
    <!-- Renders the component mapped to "default" -->
    <router-view class="main" />
    <!-- Renders the component mapped to "footer" -->
    <router-view name="footer" class="footer" />
  </div>
</template>

The route maps each name to a component. The default key is used for the unnamed <router-view>.

const router = createRouter({
  routes: [
    {
      path: '/',
      components: {
        // Renders to <router-view />
        default: Home,
        // Renders to <router-view name="sidebar" />
        sidebar: MainSidebar,
        // Renders to <router-view name="footer" />
        footer: MainFooter,
      },
    },
  ],
})

The components option is plural. Using component singular on a route with named views is a common mistake that results in only one view rendering .

Named views can be combined with nested routes. The parent route uses component singular for the parent component, and a child route uses components plural for its own named views. The nested <router-view> inside the parent can also have a name, which is how complex layouts with multiple independent panels are built .

// Nested named views
{
  path: '/settings',
  component: UserSettings, // Parent component
  children: [
    {
      path: 'profile',
      components: {
        default: UserProfile,    // Renders to <router-view /> in UserSettings
        helper: UserProfilePreview, // Renders to <router-view name="helper" />
      },
    },
  ],
}

c. Aliases: multiple paths, one route

An alias is a path that matches a route record without changing the URL. The difference from a redirect is precise: a redirect replaces the URL and triggers a new navigation; an alias keeps the URL the user typed but matches the record’s component .

const router = createRouter({
  routes: [
    {
      path: '/',
      component: Homepage,
      // Visiting /home renders Homepage but URL stays /home
      alias: '/home',
    },
  ],
})

The alias can be a string or an array of strings. It can be absolute (starting with /) or relative. In nested routes, an absolute alias is often necessary to make the alias independent of the parent path .

{
  path: '/users',
  component: UsersLayout,
  children: [
    {
      path: 'list',
      component: UserList,
      // All three URLs render UserList:
      // /users/list, /people, /users
      alias: ['/people', ''],
    },
  ],
}

If the route has params, the alias must include the same params. An absolute alias that omits the param will not match correctly .

{
  path: '/users/:id',
  component: UsersByIdLayout,
  children: [
    {
      path: 'profile',
      component: UserDetails,
      // /users/24/profile, /users/24, and /24 all render UserDetails
      alias: ['/:id', ''],
    },
  ],
}

The SEO caveat is worth noting. When a route is reachable through multiple URLs, search engines may index the alias instead of the canonical path. The Vue Router documentation recommends defining a canonical link in the page head to indicate which URL is the preferred one .


Complete Example Session

The following session builds a settings page with a nested layout, a named helper view, and an alias for a legacy URL.

// ============================================
// PART 1: THE ROUTE CONFIGURATION
// ============================================
import { createRouter, createWebHistory } from 'vue-router'
import UserSettings from './UserSettings.vue'
import UserEmails from './UserEmails.vue'
import UserProfile from './UserProfile.vue'
import UserProfilePreview from './UserProfilePreview.vue'

const router = createRouter({
  history: createWebHistory(),
  routes: [
    {
      // Parent route: /settings
      path: '/settings',
      component: UserSettings,
      // Alias the parent so /preferences also renders UserSettings
      alias: '/preferences',
      children: [
        // Default child: renders at /settings
        { path: '', redirect: 'profile' },
        {
          // Child route: /settings/emails
          path: 'emails',
          component: UserEmails,
        },
        {
          // Child route with named views: /settings/profile
          path: 'profile',
          components: {
            // Renders to the default <router-view> in UserSettings
            default: UserProfile,
            // Renders to <router-view name="helper" /> in UserSettings
            helper: UserProfilePreview,
          },
          // Alias this child so /profile also works
          alias: ['/profile'],
        },
      ],
    },
  ],
})
<!-- ============================================
     PART 2: THE PARENT COMPONENT
     ============================================ -->
<!-- UserSettings.vue -->
<template>
  <div class="settings">
    <h1>User Settings</h1>
    <!-- Navigation is always visible -->
    <nav>
      <router-link to="/settings/profile">Profile</router-link>
      <router-link to="/settings/emails">Emails</router-link>
    </nav>

    <!-- Default child outlet: UserProfile or UserEmails -->
    <router-view />

    <!-- Named outlet: UserProfilePreview (only on profile) -->
    <router-view name="helper" />
  </div>
</template>

The route configuration uses children to nest the email and profile views inside UserSettings. The profile child uses components (plural) to render both UserProfile and UserProfilePreview at the same time. The parent route has an alias /preferences, and the profile child has an alias /profile. Visiting /preferences/profile renders the same components as /settings/profile, but the URL stays /preferences/profile.


Quick Reference

Nested Routes vs Named Views

AspectNested RoutesNamed Views
Config keychildrencomponents (plural)
RenderingInside parent’s <router-view>In sibling <router-view> outlets
RelationshipParent-child hierarchyParallel at the same level
Outlet nameDefault (unnamed)Matches key in components

Nested Path Rules

PathBehavior
'profile'Appended to parent path
''Matches parent path exactly
'/absolute'Root path, component still nested

Named View Configuration

KeyOutlet
default<router-view />
sidebar<router-view name="sidebar" />
helper<router-view name="helper" />

Redirect vs Alias

PropertyURL ChangesComponent RendersGuards
redirectYesAt targetOn target only
aliasNoSame recordOn the record

Best Practices

✅ Do This:

// Use children for hierarchy
{ path: '/user/:id', component: User, children: [{ path: 'profile', component: Profile }] }

// Use components plural for named views
{ path: '/', components: { default: Home, sidebar: Sidebar } }

// Use empty path for default child
{ path: '', component: UserHome }

// Use alias to keep legacy URLs working
{ path: '/', component: Home, alias: '/home' }

❌ Don’t Do This:

// Using component singular with multiple outlets
{ path: '/', component: { default: Home, sidebar: Sidebar } }

// Expecting child to render without parent <router-view>
{ path: '/user', component: User, children: [{ path: 'profile', component: Profile }] } // no <router-view> in User

// Using redirect when the URL should stay the same
{ path: '/home', redirect: '/' } // URL changes to /

Common Pitfalls

PitfallWhy It HappensFix
Child route not renderingParent lacks <router-view>Add outlet to parent component
Named view not renderingUsed component not componentsUse plural components
Empty outlet at parent pathNo default childAdd { path: '', component: ... }
Alias not matching paramsAlias omits paramsInclude :id in alias
Redirect changes URLConfused alias with redirectUse alias not redirect

Real-World Examples

1. Nested child route

// Renders inside User's <router-view>
{ path: '/user/:id', component: User, children: [{ path: 'profile', component: Profile }] }

2. Default child

// Renders UserHome at /user/:id
{ path: '', component: UserHome }

3. Named view configuration

// Multiple outlets for one route
{ path: '/', components: { default: Home, sidebar: Sidebar } }

4. Nested named view

// Child route with its own named outlets
{ path: 'profile', components: { default: UserProfile, helper: Preview } }

5. Absolute alias in nested route

// /people renders UserList regardless of parent
{ path: 'list', component: UserList, alias: '/people' }

6. Alias with params

// /:id matches the same route as /users/:id/profile
{ path: 'profile', component: UserDetails, alias: ['/:id', ''] }

7. Redirect vs alias

// Redirect: URL changes to /
{ path: '/home', redirect: '/' }
// Alias: URL stays /home
{ path: '/', component: Home, alias: '/home' }

8. Absolute nested path

// Component nested but URL is root-level
{ path: '/user/:id', component: User, children: [{ path: '/settings', component: Settings }] }

9. Parent redirect with children

// Parent must have component when children + redirect
{ path: '/settings', component: Settings, redirect: '/settings/profile', children: [...] }

10. Named view with nested route

<!-- UserSettings.vue -->
<router-view /> <!-- default child -->
<router-view name="helper" /> <!-- named child -->

Visual

Nested Routes

┌──────────────────────────────────────────────┐
│  User.vue (parent)                           │
│  ┌────────────────────────────────────────┐  │
│  │ <h2>User {{ $route.params.id }}</h2>   │  │
│  │                                        │  │
│  │ <router-view>                          │  │
│  │  ┌──────────────────────────────────┐  │  │
│  │  │ UserProfile.vue (child)          │  │  │
│  │  │ Renders inside parent's outlet   │  │  │
│  │  └──────────────────────────────────┘  │  │
│  └────────────────────────────────────────┘  │
└──────────────────────────────────────────────┘

Named Views

┌──────────────────────────────────────────────┐
│  App.vue                                     │
│  ┌────────┐ ┌────────────────┐ ┌────────┐   │
│  │sidebar │ │    default     │ │ footer │   │
│  │ outlet │ │    outlet      │ │ outlet │   │
│  └────────┘ └────────────────┘ └────────┘   │
│                                              │
│  One route → three components                │
│  components: { default, sidebar, footer }    │
└──────────────────────────────────────────────┘

Redirect vs Alias

┌──────────────────────────────────────────────┐
│  REDIRECT                                    │
│  Visit /home → URL becomes / → renders Home  │
│  URL: /home ❌                               │
│  URL: / ✅                                   │
│                                              │
│  ALIAS                                       │
│  Visit /home → URL stays /home → renders Home│
│  URL: /home ✅                               │
└──────────────────────────────────────────────┘

Named Views with Nested Routes

┌──────────────────────────────────────────────┐
│  UserSettings.vue                            │
│  ┌────────────────────────────────────────┐  │
│  │ <h1>User Settings</h1>                 │  │
│  │ <nav>...</nav>                         │  │
│  │                                        │  │
│  │ <router-view />        ← default child │  │
│  │ <router-view name="helper" /> ← helper │  │
│  └────────────────────────────────────────┘  │
│                                              │
│  Route: components: { default, helper }      │
└──────────────────────────────────────────────┘

Summary

ItemValue
Nested routeschildren array, parent has <router-view>
Default childpath: ''
Named viewscomponents (plural) object
Default view namedefault
Nested named viewName the nested <router-view>
Aliasalias property, URL unchanged
Redirectredirect property, URL changes
Absolute nested pathStarts with /, component still nested
Alias with paramsMust include params in alias

Key takeaways:

  • Nested routes render inside the parent. The parent component must contain a <router-view>, and the children array defines the routes that render into it .
  • Named views render side by side. The components object maps each <router-view name="..."> to a component. The unnamed outlet uses the default key .
  • An empty path is the default child. { path: '', component: Home } renders when the parent path matches exactly, preventing an empty outlet .
  • Paths starting with / are root-level. The component is still nested, but the URL does not include the parent segment .
  • Aliases keep the URL unchanged. A user visiting the alias sees the alias URL, but the route matches the original record. A redirect changes the URL .
  • Aliases with params must include the params. An absolute alias that omits :id will not match the param route correctly .
  • Named views can be nested. A child route can use components to render multiple views into a parent component’s named outlets .

Remember: Nested routes, named views, and aliases solve three different problems. Nested routes answer “where does this component render?”—inside the parent. Named views answer “how do I render multiple components at once?”—through parallel outlets. Aliases answer “how do I make this route reachable from another URL without changing the URL?”—by matching the record under a second path. The first is about hierarchy, the second is about parallelism, and the third is about identity. Confusing them produces layouts that do not compose, URLs that break when shared, and components that render in the wrong outlet.


Was this helpful?


Stop using slow, ad-bloated tool sites! 🤮

🔎 Search “KandZ Tools” on Google to use many professional utilities for free.

KandZ.me is the ultimate minimalist hub for:
✅ Finance (Mortgage, Interest, Inflation)
✅ Tech (Base64, JSON, Dev Suite, IP)
✅ Health (BMI, BMR, TDEE)
✅ Productivity (Timer, Workspace, QR)

⚡️ Fast & Private
🔒 No data leaves your device
💎 100% Free

🔗 Use it now: https://tools.kandz.me
🔖 Bookmark it—you’ll need it later!