最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Element-UI結合遞歸組件實現后臺管理系統(tǒng)左側菜單

 更新時間:2024年09月12日 08:32:37   作者:你不講 wood  
在Vue.js中使用遞歸組件可以方便地構建多層級的菜單結構,遞歸組件適用于處理具有嵌套關系的數據,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

在 Vue.js 中,允許你編寫一個組件來表示一個節(jié)點,而這個節(jié)點可以包含多個子節(jié)點,每個子節(jié)點又可以是同樣的組件。這種方式使得組件能夠處理無限層級的嵌套結構。

應用場景

遞歸組件非常適合處理具有層級結構的數據,以下是幾種常見的應用場景:

  • 多級菜單:如上所示,遞歸組件可以用來生成多級菜單,無論是水平還是垂直布局。
  • 文件目錄樹:文件系統(tǒng)中的目錄結構通常是樹狀的,遞歸組件可以幫助你輕松地構建一個文件目錄樹。
  • 評論系統(tǒng):許多網站的評論系統(tǒng)支持回復評論,形成一個樹形結構,遞歸組件可以用來展示這些評論及其回復。
  • 組織架構圖:公司內部的組織結構也可以用遞歸組件來表示,每個部門下面可以有子部門或員工。
  • 任務列表:在項目管理工具中,任務列表往往包含父任務和子任務,遞歸組件可以清晰地展現這種層次關系。

實現步驟

1. 安裝 Element-UI

確保你的項目已經安裝了 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. 設計菜單數據結構

先定義一個合理的菜單數據結構,通常是一個數組對象,其中每個對象代表一個菜單項,并且可以包含子菜單。例如:

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)建一個遞歸組件來渲染菜單項。這個組件將根據傳入的數據結構遞歸地生成菜單項。

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 組件,并傳遞菜單數據:

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>

實現效果

在這里插入圖片描述

總結

Element-UI 結合遞歸組件的方式,用于構建后臺管理系統(tǒng)的左側菜單,主要是通過以下步驟實現的:

  • 配置路由(Routes): 首先,如同前述代碼片段所示,定義一系列路由對象構成的數組 routes,這些對象不僅描述了各頁面路徑(path)、頁面名稱(name)、對應組件(component),還包括了嵌套的子路由(children)以及元信息(如頁面標題)等,從而形成了多級菜單的結構基礎。

  • 遞歸組件(Recursive Component): 利用 Vue 中的遞歸組件技術,創(chuàng)建一個菜單組件,該組件根據傳入的路由配置(通常是 routes 數組)自動生成菜單項。遞歸的邏輯在于:組件內根據當前路由的 children 屬性判斷是否有子菜單,如果有,則繼續(xù)渲染子菜單組件,直至沒有更多子節(jié)點,以此實現無限級菜單的展現。

  • Element-UI 風格: 在實現遞歸菜單組件時,利用 Element-UI 的 UI 組件庫(如 el-menu、el-submenu、el-menu-item 等),為菜單項賦予統(tǒng)一且美觀的樣式,實現折疊、展開、激活狀態(tài)等交互效果,增強用戶體驗。

總結而言,Element-UI 與遞歸組件結合的方式,使得后臺管理系統(tǒng)的左側菜單能夠高效地根據路由配置動態(tài)渲染多層級菜單,同時確保了菜單的一致性和美觀性,提升了系統(tǒng)的可維護性和用戶體驗。

到此這篇關于Elemnt-UI + 遞歸組件實現后臺管理系統(tǒng)左側菜單的文章就介紹到這了,更多相關Elemnt-UI + 遞歸組件實現后臺管理系統(tǒng)左側菜單內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Vue服務端渲染和Vue瀏覽器端渲染的性能對比(實例PK )

    Vue服務端渲染和Vue瀏覽器端渲染的性能對比(實例PK )

    這篇文章主要介紹了Vue服務端渲染和Vue瀏覽器端渲染的性能對比(實例PK ),非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2017-03-03
  • 了解VUE的render函數的使用

    了解VUE的render函數的使用

    本篇文章主要介紹了了解VUE的render函數的使用,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-06-06
  • 基于vue+face-api.js實現前端人臉識別功能

    基于vue+face-api.js實現前端人臉識別功能

    基于face-api.js要實現人臉識別功能,首先要將自己需要的模型文件下載保存在靜態(tài)目錄下,可以通過cdn的方式在index.html中引入face-api.js,本文給大家介紹vue+face-api.js實現前端人臉識別功能,感興趣的朋友一起看看吧
    2023-12-12
  • vue腳手架vue-cli的學習使用教程

    vue腳手架vue-cli的學習使用教程

    本篇文章主要介紹了vue腳手架vue-cli的學習使用教程,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-06-06
  • vue實現的請求服務器端API接口示例

    vue實現的請求服務器端API接口示例

    這篇文章主要介紹了vue實現的請求服務器端API接口,結合實例形式分析了vue針對post、get、patch、put等請求的封裝與調用相關操作技巧,需要的朋友可以參考下
    2019-05-05
  • vue3中7種路由守衛(wèi)的使用大全舉例

    vue3中7種路由守衛(wèi)的使用大全舉例

    最近在學習vue,感覺路由守衛(wèi)這個地方知識點挺多的,而且很重要,下面這篇文章主要給大家介紹了關于vue3中7種路由守衛(wèi)的使用大全,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2023-03-03
  • Vue中.env文件的使用詳解

    Vue中.env文件的使用詳解

    在Vue項目開發(fā)中,.env文件用于配置不同環(huán)境(開發(fā)、測試、生產)的環(huán)境變量,通過不同的文件如.env.development和.env.production來區(qū)分環(huán)境配置,Vue會根據運行命令自動加載對應的配置文件,如使用npm run serve會加載.env.development
    2024-11-11
  • vue?element-ui如何在el-tabs組件最右側添加按鈕

    vue?element-ui如何在el-tabs組件最右側添加按鈕

    這篇文章主要介紹了vue?element-ui如何在el-tabs組件最右側添加按鈕問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • vue-router中query取值的坑及解決

    vue-router中query取值的坑及解決

    這篇文章主要介紹了vue-router中query取值的坑及解決,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • vue3提示用戶版本更新方式

    vue3提示用戶版本更新方式

    本文介紹了如何在項目中創(chuàng)建和使用自定義插件,以在構建過程中檢查版本號,具體步驟包括在項目根目錄下創(chuàng)建buildLifeHook.ts文件,并在public目錄下創(chuàng)建version文件夾,然后在vite.config.ts中引用該插件,并在src/utils目錄下創(chuàng)建XxzUtils.ts文件
    2024-12-12

最新評論

会理县| 阿尔山市| 逊克县| 方正县| 汉阴县| 河北省| 阿城市| 玛多县| 九龙县| 定陶县| 南京市| 化德县| 亚东县| 武宣县| 福泉市| 珠海市| 盱眙县| 澜沧| 雅安市| 江西省| 饶阳县| 那曲县| 城口县| 宁武县| 遂宁市| 新建县| 祥云县| 阿城市| 新龙县| 河东区| 瑞金市| 丹巴县| 澜沧| 福州市| 武定县| 滦南县| 诸城市| 甘孜县| 盐池县| 石景山区| 富阳市|