SoFunction
Updated on 2025-04-14

Detailed explanation of various usages of Vue nested routing

1. Vue nested routing basics

1. Define nested routes

In Vue Router, nested routing can be achieved by defining the children attribute in the routing configuration. For example, the following is a simple nested routing configuration:

import { createRouter, createWebHistory } from 'vue-router';

const routes = [
  {
    path: '/',
    component: () => import('./views/'),
  },
  {
    path: '/dashboard',
    component: () => import('./views/'),
    children: [
      {
        path: 'profile',
        component: () => import('./views/'),
      },
      {
        path: 'settings',
        component: () => import('./views/'),
      },
    ],
  },
];

const router = createRouter({
  history: createWebHistory(),
  routes,
});

export default router;

In this example, /dashboard is the parent route, and /dashboard/profile and /dashboard/settings are the child routes.

2. Use nested routing

In the parent component, the child routing components can be rendered by:

<template>
  <el-menu :default-active="$" router>
    <el-menu-item index="/home">front page</el-menu-item>
    <el-menu-item index="/users">User Management</el-menu-item>
    <el-sub-menu index="/dashboard">
      &lt;template #title>Dashboard</template>      &lt;el-menu-item index="/dashboard/profile"&gt;Personal Profile&lt;/el-menu-item&gt;
      &lt;el-menu-item index="/dashboard/settings"&gt;set up&lt;/el-menu-item&gt;
    &lt;/el-sub-menu&gt;
  &lt;/el-menu&gt;
&lt;/template&gt;

2. Basic usage of Element Plus Menu

Element Plus' Menu components support a variety of usages, including horizontal menus, vertical menus, folded menus, and more. Here are some basic usages:

1. Vertical menu

&lt;template&gt;
  &lt;el-menu :default-active="$" router&gt;
    &lt;el-menu-item index="/home"&gt;front page&lt;/el-menu-item&gt;
    &lt;el-menu-item index="/users"&gt;User Management&lt;/el-menu-item&gt;
    &lt;el-sub-menu index="/dashboard"&gt;
      &lt;template #title>Dashboard</template>      &lt;el-menu-item index="/dashboard/profile"&gt;Personal Profile&lt;/el-menu-item&gt;
      &lt;el-menu-item index="/dashboard/settings"&gt;set up&lt;/el-menu-item&gt;
    &lt;/el-sub-menu&gt;
  &lt;/el-menu&gt;
&lt;/template&gt;

In this example, the router attribute of el-menu is used to activate the menu item corresponding to the current route.

2. Horizontal menu

The horizontal menu can be implemented by setting mode="horizontal":

&lt;template&gt;
  &lt;el-menu mode="horizontal" :default-active="$" router&gt;
    &lt;el-menu-item index="/home"&gt;front page&lt;/el-menu-item&gt;
    &lt;el-menu-item index="/users"&gt;User Management&lt;/el-menu-item&gt;
    &lt;el-sub-menu index="/dashboard"&gt;
      &lt;template #title>Dashboard</template>      &lt;el-menu-item index="/dashboard/profile"&gt;Personal Profile&lt;/el-menu-item&gt;
      &lt;el-menu-item index="/dashboard/settings"&gt;set up&lt;/el-menu-item&gt;
    &lt;/el-sub-menu&gt;
  &lt;/el-menu&gt;
&lt;/template&gt;

3. The combination of Vue nested routing and Element Plus Menu

1. Dynamic menu

Menu items can be generated by dynamically binding data. For example, get menu data from the backend and render:

&lt;template&gt;
  &lt;el-menu :default-active="$" router&gt;
    &lt;template v-for="item in menuData" :key=""&gt;
      &lt;el-menu-item v-if="!" :index=""&gt;
        {{  }}
      &lt;/el-menu-item&gt;
      &lt;el-sub-menu v-else :index=""&gt;
        &lt;template #title&gt;{{  }}&lt;/template&gt;
        &lt;el-menu-item v-for="child in " :key="" :index=""&gt;
          {{  }}
        &lt;/el-menu-item&gt;
      &lt;/el-sub-menu&gt;
    &lt;/template&gt;
  &lt;/el-menu&gt;
&lt;/template&gt;

&lt;script setup&gt;
import { ref } from 'vue';

const menuData = ref([
  { index: '/home', label: 'front page' },
  { index: '/users', label: 'User Management' },
  {
    index: '/dashboard',
    label: 'Dashboard',
    children: [
      { index: '/dashboard/profile', label: 'Profile' },
      { index: '/dashboard/settings', label: 'set up' },
    ],
  },
]);
&lt;/script&gt;

In this example, menuData is a dynamically generated array of menu data.

2. Routing mode

When used in conjunction with Vue Router, the menu item corresponding to the current route can be activated through the router property. For example:

&lt;template&gt;
  &lt;el-menu :default-active="$" router&gt;
    &lt;el-menu-item index="/home"&gt;front page&lt;/el-menu-item&gt;
    &lt;el-menu-item index="/users"&gt;User Management&lt;/el-menu-item&gt;
    &lt;el-sub-menu index="/dashboard"&gt;
      &lt;template #title>Dashboard</template>      &lt;el-menu-item index="/dashboard/profile"&gt;Personal Profile&lt;/el-menu-item&gt;
      &lt;el-menu-item index="/dashboard/settings"&gt;set up&lt;/el-menu-item&gt;
    &lt;/el-sub-menu&gt;
  &lt;/el-menu&gt;
&lt;/template&gt;

In this example, the router attribute of el-menu will automatically activate the corresponding menu item based on the current routing path ($).

3. Menu event handling

Element Plus' Menu components provide a variety of events, such as select, open, and close. These events can be used to handle the interactive logic of the menu. For example:

&lt;template&gt;
  &lt;el-menu :default-active="$" router @select="handleSelect"&gt;
    &lt;el-menu-item index="/home"&gt;front page&lt;/el-menu-item&gt;
    &lt;el-menu-item index="/users"&gt;User Management&lt;/el-menu-item&gt;
    &lt;el-sub-menu index="/dashboard"&gt;
      &lt;template #title>Dashboard</template>      &lt;el-menu-item index="/dashboard/profile"&gt;Personal Profile&lt;/el-menu-item&gt;
      &lt;el-menu-item index="/dashboard/settings"&gt;set up&lt;/el-menu-item&gt;
    &lt;/el-sub-menu&gt;
  &lt;/el-menu&gt;
&lt;/template&gt;

&lt;script setup&gt;
import { ref } from 'vue';

const handleSelect = (index) =&gt; {
  (`Selected menu: ${index}`);
};
&lt;/script&gt;

In this example, the handleSelect method is fired when the menu item is selected.

4. Advanced usage

1. Permission Control

In actual applications, it is usually necessary to dynamically display menu items based on user permissions. It can be filtered by adding permission attributes in the routing configuration and rendering the menu. For example:

const routes = [
  {
    path: '/home',
    component: () => import('./views/'),
    meta: { requiresAuth: false },
  },
  {
    path: '/users',
    component: () => import('./views/'),
    meta: { requiresAuth: true },
  },
  {
    path: '/dashboard',
    component: () => import('./views/'),
    children: [
      {
        path: 'profile',
        component: () => import('./views/'),
        meta: { requiresAuth: true },
      },
      {
        path: 'settings',
        component: () => import('./views/'),
        meta: { requiresAuth: true },
      },
    ],
  },
];

Then when the menu renders, filter the menu items according to user permissions:

&lt;template&gt;
  &lt;el-menu :default-active="$" router&gt;
    &lt;template v-for="item in filteredMenuData" :key=""&gt;
      &lt;el-menu-item v-if="!" :index=""&gt;
        {{  }}
      &lt;/el-menu-item&gt;
      &lt;el-sub-menu v-else :index=""&gt;
        &lt;template #title&gt;{{  }}&lt;/template&gt;
        &lt;el-menu-item v-for="child in " :key="" :index=""&gt;
          {{  }}
        &lt;/el-menu-item&gt;
      &lt;/el-sub-menu&gt;
    &lt;/template&gt;
  &lt;/el-menu&gt;
&lt;/template&gt;

&lt;script setup&gt;
import { ref, computed } from 'vue';
import { useStore } from 'vuex';

const store = useStore();

const menuData = ref([
  { index: '/home', label: 'front page', meta: { requiresAuth: false } },
  { index: '/users', label: 'User Management', meta: { requiresAuth: true } },
  {
    index: '/dashboard',
    label: 'Dashboard',
    children: [
      { index: '/dashboard/profile', label: 'Profile', meta: { requiresAuth: true } },
      { index: '/dashboard/settings', label: 'set up', meta: { requiresAuth: true } },
    ],
  },
]);

const filteredMenuData = computed(() =&gt; {
  return ((item) =&gt; {
    if (!) {
      return ! || ;
    } else {
       = ((child) =&gt; {
        return ! || ;
      });
      return  &gt; 0;
    }
  });
});
&lt;/script&gt;

In this example, filteredMenuData is a computed property that dynamically filters menu items based on the user's authentication status().

2. Dynamic loading of menus

In some cases, menu data may need to be loaded dynamically from the backend. Menu data can be obtained through asynchronous requests and the menu can be rendered after the acquisition is completed. For example:

<template>
  <el-menu :default-active="$" router v-if=" > 0">
    <template v-for="item in menuData" :key="">
      <el-menu-item v-if="!" :index="">
        {{  }}
      </el-menu-item>
      <el-sub-menu v-else :index="">
        <template #title>{{  }}</template>
        <el-menu-item v-for="child in " :key="" :index="">
          {{  }}
        </el-menu-item>
      </el-sub-menu>
    </template>
  </el-menu>
</template>

<script setup>
import { ref, onMounted } from 'vue';
import axios from 'axios';

const menuData = ref([]);

onMounted(async () => {
  try {
    const response = await ('/api/menu');
     = ;
  } catch (error) {
    ('Failed to load menu data:', error);
  }
});
</script>

In this example, the onMounted lifecycle hook is used to load menu data from the backend when the component is mounted.

3. Internationalization of menus

In international applications, the title of a menu item may need to be displayed dynamically based on the user's language preferences. The internationalization of menus can be achieved through Vue I18n. For example:

&lt;template&gt;
  &lt;el-menu :default-active="$" router&gt;
    &lt;template v-for="item in menuData" :key=""&gt;
      &lt;el-menu-item v-if="!" :index=""&gt;
        {{ $t() }}
      &lt;/el-menu-item&gt;
      &lt;el-sub-menu v-else :index=""&gt;
        &lt;template #title&gt;{{ $t() }}&lt;/template&gt;
        &lt;el-menu-item v-for="child in " :key="" :index=""&gt;
          {{ $t() }}
        &lt;/el-menu-item&gt;
      &lt;/el-sub-menu&gt;
    &lt;/template&gt;
  &lt;/el-menu&gt;
&lt;/template&gt;

&lt;script setup&gt;
import { ref } from 'vue';
import { useI18n } from 'vue-i18n';

const { t } = useI18n();

const menuData = ref([
  { index: '/home', label: '' },
  { index: '/users', label: '' },
  {
    index: '/dashboard',
    label: '',
    children: [
      { index: '/dashboard/profile', label: '' },
      { index: '/dashboard/settings', label: '' },
    ],
  },
]);
&lt;/script&gt;

&lt;i18n&gt;
{
  "en": {
    "menu": {
      "home": "Home",
      "users": "Users",
      "dashboard": "Dashboard",
      "profile": "Profile",
      "settings": "Settings"
    }
  },
  "zh": {
    "menu": {
      "home": "front page",
      "users": "User Management",
      "dashboard": "Dashboard",
      "profile": "Personal Profile",
      "settings": "set up"
    }
  }
}
&lt;/i18n&gt;

In this example, the $t method is used to dynamically translate the title of a menu item.

4. Collapse and expand menu

Element Plus' Menu components support folding and expanding. You can control the collapse state of the menu by setting the collapse property. For example:

&lt;template&gt;
  &lt;div&gt;
    &lt;el-button @click="toggleCollapse"&gt;Switch menu&lt;/el-button&gt;
    &lt;el-menu :default-active="$" router :collapse="isCollapsed"&gt;
      &lt;el-menu-item index="/home"&gt;front page&lt;/el-menu-item&gt;
      &lt;el-menu-item index="/users"&gt;User Management&lt;/el-menu-item&gt;
      &lt;el-sub-menu index="/dashboard"&gt;
        &lt;template #title>Dashboard</template>        &lt;el-menu-item index="/dashboard/profile"&gt;Personal Profile&lt;/el-menu-item&gt;
        &lt;el-menu-item index="/dashboard/settings"&gt;set up&lt;/el-menu-item&gt;
      &lt;/el-sub-menu&gt;
    &lt;/el-menu&gt;
  &lt;/div&gt;
&lt;/template&gt;

&lt;script setup&gt;
import { ref } from 'vue';

const isCollapsed = ref(false);

const toggleCollapse = () =&gt; {
   = !;
};
&lt;/script&gt;

In this example, isCollapsed is a responsive variable that controls the collapsed state of the menu. When the button is clicked, the toggleCollapse method will toggle the collapsed state of the menu.

5. Custom styles for menus

You can adjust the style of the menu through custom CSS. For example:

.el-menu {
  background-color: #f5f7fa;
  border-right: none;
}

.el-menu-item {
  color: #333;
}

.-active {
  background-color: #409eff;
  color: #fff;
}

.el-sub-menu__title {
  color: #333;
}

.el-sub-menu__title:hover {
  background-color: #e6f7ff;
}

In this example, the menu's background color, font color, and style of activation status are customized.

V. Complete example

Here is a complete example combining nested routing, dynamic menus, permission control, internationalization, and collapse:

  • Routing configuration
import { createRouter, createWebHistory } from 'vue-router';

const routes = [
  {
    path: '/',
    component: () => import('./views/'),
    meta: { requiresAuth: false },
  },
  {
    path: '/users',
    component: () => import('./views/'),
    meta: { requiresAuth: true },
  },
  {
    path: '/dashboard',
    component: () => import('./views/'),
    children: [
      {
        path: 'profile',
        component: () => import('./views/'),
        meta: { requiresAuth: true },
      },
      {
        path: 'settings',
        component: () => import('./views/'),
        meta: { requiresAuth: true },
      },
    ],
    meta: { requiresAuth: true },
  },
];

const router = createRouter({
  history: createWebHistory(),
  routes,
});

export default router;
  • Menu Components
&lt;template&gt;
  &lt;div&gt;
    &lt;el-button @click="toggleCollapse"&gt;Switch menu&lt;/el-button&gt;
    &lt;el-menu :default-active="$" router :collapse="isCollapsed"&gt;
      &lt;template v-for="item in filteredMenuData" :key=""&gt;
        &lt;el-menu-item v-if="!" :index=""&gt;
          {{ $t() }}
        &lt;/el-menu-item&gt;
        &lt;el-sub-menu v-else :index=""&gt;
          &lt;template #title&gt;{{ $t() }}&lt;/template&gt;
          &lt;el-menu-item v-for="child in " :key="" :index=""&gt;
            {{ $t() }}
          &lt;/el-menu-item&gt;
        &lt;/el-sub-menu&gt;
      &lt;/template&gt;
    &lt;/el-menu&gt;
  &lt;/div&gt;
&lt;/template&gt;

&lt;script setup&gt;
import { ref, computed } from 'vue';
import { useStore } from 'vuex';
import { useI18n } from 'vue-i18n';

const { t } = useI18n();
const store = useStore();

const menuData = ref([
  { index: '/home', label: '', meta: { requiresAuth: false } },
  { index: '/users', label: '', meta: { requiresAuth: true } },
  {
    index: '/dashboard',
    label: '',
    children: [
      { index: '/dashboard/profile', label: '', meta: { requiresAuth: true } },
      { index: '/dashboard/settings', label: '', meta: { requiresAuth: true } },
    ],
    meta: { requiresAuth: true },
  },
]);

const isCollapsed = ref(false);

const toggleCollapse = () =&gt; {
   = !;
};

const filteredMenuData = computed(() =&gt; {
  return ((item) =&gt; {
    if (!) {
      return ! || ;
    } else {
       = ((child) =&gt; {
        return ! || ;
      });
      return  &gt; 0;
    }
  });
});
&lt;/script&gt;

&lt;i18n&gt;
{
  "en": {
    "menu": {
      "home": "Home",
      "users": "Users",
      "dashboard": "Dashboard",
      "profile": "Profile",
      "settings": "Settings"
    }
  },
  "zh": {
    "menu": {
      "home": "front page",
      "users": "User Management",
      "dashboard": "Dashboard",
      "profile": "Personal Profile",
      "settings": "set up"
    }
  }
}
&lt;/i18n&gt;
  • style
.el-menu {
  background-color: #f5f7fa;
  border-right: none;
}

.el-menu-item {
  color: #333;
}

.-active {
  background-color: #409eff;
  color: #fff;
}

.el-sub-menu__title {
  color: #333;
}

.el-sub-menu__title:hover {
  background-color: #e6f7ff;
}

6. Summary

A feature-rich and flexible navigation menu can be achieved by combining Vue nested routing and Element Plus’ Menu components. This article introduces a variety of scenarios from basic usage to advanced features, including dynamic menus, permission control, internationalization, folding functions, and custom styles. These functions can be flexibly combined according to actual needs to meet the needs of complex applications.

The above is a detailed explanation of the various usages of Vue nested routing. For more information on the usage of Vue nested routing, please pay attention to my other related articles!