Vue-Element-Admin Breadcrumb Generation Algorithm: Handling Nested Routes with Route Meta

The breadcrumb generation algorithm in PanJiaChen/vue-element-admin dynamically assembles navigation trails by filtering this.$route.matched for records containing meta.title, prepending a Dashboard entry when needed, and respecting meta.breadcrumb: false to hide specific nested routes.

Vue-element-admin constructs breadcrumbs through systematic traversal of matched route records rather than static configuration. The implementation lives in src/components/Breadcrumb/index.vue and leverages Vue Router's matched array to automatically reflect nested hierarchies. This approach allows developers to control breadcrumb visibility and labels directly through route meta properties without modifying component logic.

How the Breadcrumb Generation Algorithm Works

The core algorithm follows a four-step filtration process inside the getBreadcrumb() method. It begins by extracting the hierarchy from the current route object.

Step 1: Collect Matched Routes with Meta Titles

The algorithm accesses this.$route.matched, which contains every route record from root to deepest child. It immediately filters this array to keep only entries that define a display title.

let matched = this.$route.matched.filter(item => item.meta && item.meta.title)

This ensures that routes without human-readable labels never appear in the breadcrumb trail.

Step 2: Ensure Dashboard Root Entry

If the first matched record is not the dashboard route, the algorithm injects a synthetic Dashboard entry at the beginning of the array. This guarantees the breadcrumb always starts at the home page.

const first = matched[0]
if (!this.isDashboard(first)) {
  matched = [{ path: '/dashboard', meta: { title: 'Dashboard' } }].concat(matched)
}

The isDashboard() helper checks the route name case-insensitively to determine if the root is already present.

Step 3: Filter by Breadcrumb Visibility Flag

Routes can opt out of breadcrumb display by setting meta.breadcrumb: false. The final list removes these entries while preserving the hierarchy of visible parents.

this.levelList = matched.filter(
  item => item.meta && item.meta.title && item.meta.breadcrumb !== false
)

The resulting levelList array drives the template rendering.

Step 4: Render with Navigation Logic

The template iterates levelList, rendering each item as plain text if it is the last item or has redirect: 'noRedirect', otherwise as a clickable link.

<el-breadcrumb class="app-breadcrumb" separator="/">
  <transition-group name="breadcrumb">
    <el-breadcrumb-item v-for="(item, index) in levelList" :key="item.path">
      <span v-if="item.redirect==='noRedirect' || index===levelList.length-1" class="no-redirect">
        {{ item.meta.title }}
      </span>
      <a v-else @click.prevent="handleLink(item)">{{ item.meta.title }}</a>
    </el-breadcrumb-item>
  </transition-group>
</el-breadcrumb>

Handling Nested Routes with Route Meta Properties

Nested routes in vue-element-admin are defined under src/router/modules/nested.js. The breadcrumb algorithm naturally handles arbitrary depth because this.$route.matched preserves parent-child ordering.

Route Configuration Example

Consider this three-level nested structure:

{
  path: '/nested',
  component: Layout,
  redirect: '/nested/menu1',
  name: 'Nested',
  meta: { title: 'Nested', icon: 'nested' },
  children: [
    {
      path: 'menu1',
      name: 'Menu1',
      meta: { title: 'Menu 1' },
      children: [
        {
          path: 'menu1-2',
          name: 'Menu1-2',
          meta: { title: 'Menu 1-2' },
          children: [
            { path: 'menu1-2-1', name: 'Menu1-2-1', meta: { title: 'Menu 1-2-1' } }
          ]
        }
      ]
    }
  ]
}

When navigating to /nested/menu1/menu1-2/menu1-2-1, the matched array contains four records: /nested, /nested/menu1, /nested/menu1/menu1-2, and the final leaf route. The algorithm transforms this into:

Dashboard / Nested / Menu 1 / Menu 1-2 / Menu 1-2-1

Controlling Visibility with meta.breadcrumb

Developers can hide intermediate steps by setting breadcrumb: false in the route meta:

{
  path: 'menu1-2-1',
  name: 'Menu1-2-1',
  meta: { title: 'Menu 1-2-1', breadcrumb: false }
}

With this configuration, navigating to the same URL produces:

Dashboard / Nested / Menu 1 / Menu 1-2

The leaf route still renders its view, but disappears from the breadcrumb trail, allowing cleaner UI for modal-like or utility routes.

Source Code Implementation

The complete logic resides in src/components/Breadcrumb/index.vue, which is imported and displayed in src/layout/components/Navbar.vue. Beyond the filtration steps, the component handles dynamic path compilation for parameterized routes.

Path Compilation for Dynamic Segments

The pathCompile() method uses path-to-regexp to resolve routes containing parameters like /user/:id:

pathCompile(path) {
  const { params } = this.$route
  const toPath = require('path-to-regexp').compile(path)
  return toPath(params)
}

When users click a breadcrumb item, handleLink() either follows an explicit redirect or compiles the path dynamically:

handleLink(item) {
  if (item.redirect) return this.$router.push(item.redirect)
  this.$router.push(this.pathCompile(item.path))
}

Full getBreadcrumb Method

Here is the complete algorithm implementation as found in the source:

methods: {
  getBreadcrumb() {
    // Collect routes with titles
    let matched = this.$route.matched.filter(item => item.meta && item.meta.title)
    
    // Prepend Dashboard if not present
    const first = matched[0]
    if (!this.isDashboard(first)) {
      matched = [{ path: '/dashboard', meta: { title: 'Dashboard' } }].concat(matched)
    }
    
    // Apply breadcrumb visibility filter
    this.levelList = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false)
  },
  
  isDashboard(route) {
    const name = route && route.name
    return name && name.trim().toLowerCase() === 'dashboard'.toLowerCase()
  }
}

Summary

  • The algorithm sources data from this.$route.matched, which automatically includes all parent routes in nested hierarchies.
  • Route meta properties drive the entire breadcrumb system: meta.title provides display text, while meta.breadcrumb: false hides entries.
  • The Dashboard route serves as a synthetic root; the algorithm prepends it automatically when missing from the matched array.
  • Path compilation via path-to-regexp enables breadcrumbs to link correctly to parameterized routes.
  • Implementation resides in src/components/Breadcrumb/index.vue, with route definitions typically located in src/router/modules/nested.js.

Frequently Asked Questions

How does vue-element-admin handle deeply nested routes in breadcrumbs?

The breadcrumb generation algorithm handles arbitrary nesting depth naturally because Vue Router's this.$route.matched array already orders routes from parent to child. When you navigate to /nested/menu1/menu1-2/menu1-2-1, the matched array contains every level of the hierarchy, and the algorithm filters and renders each one that has meta.title, resulting in a complete trail from Dashboard to the deepest leaf.

Can I hide specific routes from the breadcrumb without removing them from the router?

Yes. Set meta.breadcrumb: false in the route configuration. The algorithm explicitly checks for this flag in the final filtration step: item.meta.breadcrumb !== false. This allows utility routes or modal pages to remain accessible via URL while keeping the breadcrumb trail clean and focused on primary navigation paths.

Why does the breadcrumb always show Dashboard even when I'm not on that route?

The algorithm enforces Dashboard as the root entry via a prepend operation. In getBreadcrumb(), it checks if (!this.isDashboard(first)) and inserts { path: '/dashboard', meta: { title: 'Dashboard' } } at the beginning of the matched array. This design pattern ensures users always have a visible path back to the home page from any nested location.

The component uses path-to-regexp to compile parameterized paths dynamically. The pathCompile() method takes the route's path string (e.g., /user/:id) and the current route parameters, then generates the actual URL. When users click a breadcrumb, handleLink() either uses an explicit redirect property or pushes the compiled path to the router, ensuring dynamic segments resolve correctly.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →