Element-UI結合遞歸組件實現(xiàn)后臺管理系統(tǒng)左側菜單
在 Vue.js 中,允許你編寫一個組件來表示一個節(jié)點,而這個節(jié)點可以包含多個子節(jié)點,每個子節(jié)點又可以是同樣的組件。這種方式使得組件能夠處理無限層級的嵌套結構。
應用場景
遞歸組件非常適合處理具有層級結構的數(shù)據(jù),以下是幾種常見的應用場景:
- 多級菜單:如上所示,遞歸組件可以用來生成多級菜單,無論是水平還是垂直布局。
- 文件目錄樹:文件系統(tǒng)中的目錄結構通常是樹狀的,遞歸組件可以幫助你輕松地構建一個文件目錄樹。
- 評論系統(tǒng):許多網(wǎng)站的評論系統(tǒng)支持回復評論,形成一個樹形結構,遞歸組件可以用來展示這些評論及其回復。
- 組織架構圖:公司內(nèi)部的組織結構也可以用遞歸組件來表示,每個部門下面可以有子部門或員工。
- 任務列表:在項目管理工具中,任務列表往往包含父任務和子任務,遞歸組件可以清晰地展現(xiàn)這種層次關系。
實現(xiàn)步驟
1. 安裝 Element-UI
確保你的項目已經(jīng)安裝了 Element-UI。如果還沒有安裝,可以通過 npm 或 yarn 來安裝:
npm install element-ui --save # 或者 yarn add element-ui
然后在 main.js 文件中引入并使用 Element-UI:
import Vue from 'vue'; import ElementUI from 'element-ui'; import 'element-ui/lib/theme-chalk/index.css'; Vue.use(ElementUI);
2. 設計菜單數(shù)據(jù)結構
先定義一個合理的菜單數(shù)據(jù)結構,通常是一個數(shù)組對象,其中每個對象代表一個菜單項,并且可以包含子菜單。例如:
import Layout from '@/Layout/index.vue'
export const routes = [
{
path: '/',
name: 'redirect',
component: Layout,
hidden: true, // 隱藏菜單
redirect: "/homePage", // 用戶在地址欄輸入 '/' 時會自動重定向到 /homePage 頁面
},
{
path: '/homePage',
component: Layout,
redirect: "/homePage/index",
meta: {
title: "首頁",
},
children: [
{
path: 'index',
name: 'homePageIndex',
meta: {
title: "首頁",
},
component: () => import('@/views/homePage/index.vue')
}
]
},
{
path: '/login',
component: () => import('@/views/login.vue'),
hidden: true
},
{
path: '/404',
component: () => import('@/views/error/404.vue'),
hidden: true
},
{
path: '/401',
component: () => import('@/views/error/401.vue'),
hidden: true
},
{
path: '/admin',
meta: {
title: "系統(tǒng)管理",
},
component: Layout,
children: [
{
path: 'user',
name: 'userIndex',
meta: {
title: "用戶管理",
},
component: () => import('@/views/admin/user.vue')
},
{
path: 'role',
name: 'roleIndex',
meta: {
title: "權限管理",
},
component: () => import('@/views/admin/role.vue'),
children: [
{
path: 'add',
name: 'addRole',
hidden: true,
meta: {
title: "添加角色",
},
component: () => import('@/views/admin/user/index.vue')
},
{
path: 'update',
name: 'updateRole',
hidden: true,
meta: {
title: "編輯角色",
},
component: () => import('@/views/admin/role/index.vue')
}
]
}
]
},
{
path: '/tableEcho',
meta: {
title: "表格管理",
},
component: Layout,
children: [
{
path: 'test',
name: 'tableEchoIndex',
meta: {
title: "表格測試",
},
component: () => import('@/views/tableEcho/index.vue'),
children: [
{
path: 'add',
name: 'addTable',
hidden: true,
meta: {
title: "新增測試",
},
component: () => import('@/views/tableEcho/add.vue')
}
]
},
],
},
]
上述示例:
- 配置了四個路由器:根路徑重定向、首頁、系統(tǒng)管理、表格管理。
- 根路徑重定向: 訪問根路徑
'/'時,會自動重定向到/homePage。 - 首頁菜單: 一個子菜單。
- 系統(tǒng)管理: 兩個子菜單, 兩個三級菜單(不展示)。
- 表格管理: 一個子菜單, 一個三級菜單(不展示)。
注意點:
每個菜單的一級路由的
component都必須是Layout組件,Layout組件用于定義整個系統(tǒng)頁面的基本結構和布局,比如導航欄、側邊欄等。通過將所有的一級路由都指向Layout組件,可以確保無論用戶訪問哪個頁面,都能看到一致的布局。
Layout 組件文件布局圖片如下

3. 創(chuàng)建遞歸組件
創(chuàng)建一個遞歸組件來渲染菜單項。這個組件將根據(jù)傳入的數(shù)據(jù)結構遞歸地生成菜單項。
Sidebar / SidebarItem.vue
<div class="sidebar_item">
<!-- 如果沒有子菜單或只有一個二級的子菜單則直接渲染 -->
<template
v-if="hasOneShowingChild(item.children, item) && (!onlyOneChild.children || onlyOneChild.noShowingChildren)"
class="item">
<router-link v-if="onlyOneChild.meta" :to="resolvePath(onlyOneChild.path)">
<el-menu-item :index="resolvePath(onlyOneChild.path)" class="title">
<img src="" alt="">
<span slot="title">{{ onlyOneChild.meta.title }}</span>
</el-menu-item>
</router-link>
</template>
<!-- 有子菜單 -->
<el-submenu v-else :index="resolvePath(item.path)" popper-append-to-body>
<template slot="title">
<span slot="title" class="title">{{ item.meta.title }}</span>
</template>
<Sidebar-item v-for="child in item.children" :key="child.path" :is-nest="true" :item="child"
:base-path="resolvePath(child.path)"></Sidebar-item>
</el-submenu>
</div>
</template>
<script>
import path from "path";
export default {
name: "SidebarItem",
data() {
return {
onlyOneChild: {
children: [],
},
}
},
props: {
item: {
type: Object,
required: true
},
basePath: {
type: String,
default: ''
}
},
methods: {
// 判斷是否只有一個子菜單
hasOneShowingChild(children = [], parent) {
// console.log('parent::: ',children , parent);
if (!children) {
children = [];
}
// 過濾掉隱藏的菜單
const showingChildren = children.filter((item) => {
// 是否隱藏菜單
if (item.hidden) {
return false;
} else {
this.onlyOneChild = item;
return true;
}
});
// 當只有一個子路由時,默認顯示子路由器
if (showingChildren.length === 1) {
return true;
}
// 如果沒有子路由,則顯示父級路由
if (showingChildren.length === 0) {
this.onlyOneChild = { ...parent, path: "", noShowingChildren: true };
return true;
}
return false;
},
// 判斷是否是外鏈
isExternal(path) {
return /^(https?:|mailto:|tel:)/.test(path);
},
// 路徑拼接
resolvePath(routePath) {
if (this.isExternal(routePath)) {
return routePath;
}
if (this.isExternal(this.basePath)) {
return this.basePath;
}
return path.resolve(this.basePath, routePath);
},
}
}
</script>
<style lang="scss" scoped>
.sidebar_item {
cursor: pointer;
>a {
height: 60px;
line-height: 60px;
}
}
::v-deep .el-submenu__title {
height: 60px;
line-height: 60px;
}
::v-deep .el-submenu__title:hover,
a :hover {
background-color: #2a9cff !important;
}
::v-deep .active {
background-color: #2a9cff !important;
}
.is-active {
background-color: #2a9cff !important;
}
.title {
font-size: 16px;
}
</style>
注意:
代碼里導入的
path模塊需要安裝 node-polyfill-webpack-plugin 模塊, 原因是由于 webpack5 中移除了nodejs核心模塊的polyfill自動引入, 所以需要下載插件手動引入
npm install node-polyfill-webpack-plugin --save # 或者 yarn add node-polyfill-webpack-plugin
vue.config.js 配置
const { defineConfig } = require('@vue/cli-service');
const nodePolyfillWebpackPlugin = require("node-polyfill-webpack-plugin");
module.exports = defineConfig({
configureWebpack: (config) => {
// 由于webpack5中移除了nodejs核心模塊的polyfill自動引入, 所以需要下載插件手動引入
config.plugins.push(new nodePolyfillWebpackPlugin());
}
})
4. 使用遞歸組件
在主布局或需要顯示菜單的地方使用 Menu 組件,并傳遞菜單數(shù)據(jù):
Sidebar / index.vue
<template>
<div style="padding-top: 30px;">
<!-- 左側菜單 -->
<el-menu :default-active="index" class="memu" @open="handleOpen" @close="handleClose" background-color="#304156"
text-color="#bfcbd9" active-text-color="#fff" @select="handleSelect">
<Sidebar-item v-for="route in sidebarRouters" :key="route.path + index" :item="route" :base-path="route.path" />
</el-menu>
</div>
</template>
<script>
import SidebarItem from './SidebarItem.vue';
import { mapGetters } from "vuex";
export default {
name: 'Sidebar',
data() {
return {
index: this.$route.path,
}
},
components: { SidebarItem },
computed: {
...mapGetters(["sidebarRouters"]),
},
methods: {
handleOpen(key, keyPath) {
console.log('handleOpen::: ', key, keyPath);
},
handleClose(key, keyPath) {
console.log('handleClose::: ', key, keyPath);
},
handleSelect(index, indexPath) {
console.log('handleSelect::: ', index, indexPath);
}
}
}
</script>
<style lang="scss" scoped>
.memu {
display: inline-block;
text-align: left;
width: 100%;
}
</style>
實現(xiàn)效果

總結
Element-UI 結合遞歸組件的方式,用于構建后臺管理系統(tǒng)的左側菜單,主要是通過以下步驟實現(xiàn)的:
配置路由(Routes): 首先,如同前述代碼片段所示,定義一系列路由對象構成的數(shù)組 routes,這些對象不僅描述了各頁面路徑(path)、頁面名稱(name)、對應組件(component),還包括了嵌套的子路由(children)以及元信息(如頁面標題)等,從而形成了多級菜單的結構基礎。
遞歸組件(Recursive Component): 利用 Vue 中的遞歸組件技術,創(chuàng)建一個菜單組件,該組件根據(jù)傳入的路由配置(通常是 routes 數(shù)組)自動生成菜單項。遞歸的邏輯在于:組件內(nèi)根據(jù)當前路由的 children 屬性判斷是否有子菜單,如果有,則繼續(xù)渲染子菜單組件,直至沒有更多子節(jié)點,以此實現(xiàn)無限級菜單的展現(xiàn)。
Element-UI 風格: 在實現(xiàn)遞歸菜單組件時,利用 Element-UI 的 UI 組件庫(如 el-menu、el-submenu、el-menu-item 等),為菜單項賦予統(tǒng)一且美觀的樣式,實現(xiàn)折疊、展開、激活狀態(tài)等交互效果,增強用戶體驗。
總結而言,Element-UI 與遞歸組件結合的方式,使得后臺管理系統(tǒng)的左側菜單能夠高效地根據(jù)路由配置動態(tài)渲染多層級菜單,同時確保了菜單的一致性和美觀性,提升了系統(tǒng)的可維護性和用戶體驗。
到此這篇關于Elemnt-UI + 遞歸組件實現(xiàn)后臺管理系統(tǒng)左側菜單的文章就介紹到這了,更多相關Elemnt-UI + 遞歸組件實現(xiàn)后臺管理系統(tǒng)左側菜單內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
vue之保留小數(shù)點兩位小數(shù) 使用filters(過濾器)
這篇文章主要介紹了vue之保留小數(shù)點兩位小數(shù) 使用filters(過濾器),具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-11-11
elementUI el-form 數(shù)據(jù)無法賦值且不報錯解決方法
本文主要介紹了elementUI el-form 數(shù)據(jù)無法賦值且不報錯解決方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2023-12-12
詳解Vue返回值動態(tài)生成表單及提交數(shù)據(jù)的辦法
這篇文章主要為大家介紹了Vue返回值動態(tài)生成表單及提交數(shù)據(jù),具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助2021-12-12

