亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Vue2集成ElementUI實(shí)現(xiàn)左側(cè)菜單導(dǎo)航功能

 更新時(shí)間:2025年04月23日 11:06:37   作者:冉成未來(lái)  
本文主要記錄兩個(gè)菜單的生成方式,通過(guò)在前端router/index.js中直接進(jìn)行配置,后端返回菜單數(shù)據(jù)進(jìn)行對(duì)應(yīng),可以通過(guò)后端返回的菜單數(shù)據(jù)控制權(quán)限,另一種是部門靜態(tài)導(dǎo)航,然后再拼接動(dòng)態(tài)導(dǎo)航,生成完成頁(yè)面導(dǎo)航,感興趣的朋友一起看看吧

簡(jiǎn)介

在開發(fā)后臺(tái)系統(tǒng)時(shí),通過(guò)菜單進(jìn)行導(dǎo)航是非常重要的一件事情,在前端開發(fā)過(guò)程中使用vue2+elementui可以快速搭建菜單導(dǎo)航,本文主要記錄兩個(gè)菜單的生成方式,通過(guò)在前端router/index.js中直接進(jìn)行配置,后端返回菜單數(shù)據(jù)進(jìn)行對(duì)應(yīng),可以通過(guò)后端返回的菜單數(shù)據(jù)控制權(quán)限;另一種是部門靜態(tài)導(dǎo)航,然后再拼接動(dòng)態(tài)導(dǎo)航,生成完成頁(yè)面導(dǎo)航。

靜態(tài)導(dǎo)航

安裝element-ui,vue-router,vuex

npm install elementui --S
npm install vue-router@3 --S
npm install vuex --S

編寫router/index.js

router/index.js

import Vue from 'vue';
import Router from 'vue-router';
Vue.use(Router);
const router = new Router({
  routes: [
    {
      path: '/',
      name: 'Home',
      component: () => import('@/views/Home.vue'),
      children: [
        {
          path: '/index',
          name: 'Index',
          component: () => import('@/views/Index.vue'),
        },
        {
          path: '/documents/note',
          name: 'NoteManagement',
          component: () => import('@/views/NoteManagement.vue'),
        },
        {
          path: '/documents/file',
          name: 'FileManagement',
          component: () => import('@/views/FileManagement.vue'),
        },
        {
          path: '/documents/newMarkdown',
          name: 'NewDocument',
          component: () => import('@/components/RichTextEditor.vue'), // 新增路由指向RichTextEditor.vue
        },
        {
          path: '/documents/newWord',
          name: 'NewWord',
          component: () => import('@/components/WordEditor.vue'),
        },
        {
          path: '/documents/newExcel',
          name: 'NewExcel',
          component: () => import('@/components/ExcelEditor.vue'),
        },
        {
          path: '/system/user',
          name: 'UserManagement',
          component: () => import('@/views/UserManagement.vue'),
        },
        {
          path: '/system/menu',
          name: 'MenuManagement',
          component: () => import('@/views/MenuManagement.vue'),
        },
        {
          path: '/system/role',
          name: 'RoleManagement',
          component: () => import('@/views/RoleManagement.vue'),
        },
        {
          path: 'system/company',
          name: 'CompanyManagement',
          component: () => import('@/views/CompanyManagement.vue'),
        },
        {
          path: '/system/dept',
          name: 'DeptManagement',
          component: () => import('@/views/DeptManagement.vue'),
        },
        {
          path: '/target',
          name: 'TargetManagement',
          component: () => import('@/views/TargetManage.vue'),
        },
        {
          path: '/targetTask',
          name: 'TargetTask',
          component: () => import('@/views/TargetTask.vue'), // 新增路由指向MonthTask.vue
        },
        {
          path: '/dayTask',
          name: 'DayTask',
          component: () => import('@/views/DayTask.vue'), // 新增路由指向DayTask.vue
        }
      ]
    },
    {
      path: '/login',
      name: 'Login',
      component: () => import('@/views/Login.vue'),
    },
    {
      path: '/register',
      name: 'Register',
      component: () => import('@/views/Register.vue'), // 更新注冊(cè)路由
    },
  ],
});
// 導(dǎo)航守衛(wèi)
// 使用 router.beforeEach 注冊(cè)一個(gè)全局前置守衛(wèi),判斷用戶是否登陸
router.beforeEach((to, from, next) => {
  if (to.path === '/login') {
    next();
  } else {
    let token = localStorage.getItem('Authorization');
    if (token === null || token === '') {
      next('/login');
    } else {
      next();
    }
  }
});
export default router;

main.js中引入elementui,router

main.js

import Vue from 'vue'
import App from './App.vue'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import store from './store'
import router from './router/index'
// import mavonEditor from 'mavon-editor'
// import 'mavon-editor/dist/css/index.css';
// import mermaidItMarkdown from 'mermaid-it-markdown'
// mavonEditor.mavonEditor.getMarkdownIt().use(mermaidItMarkdown)
// Vue.use(mavonEditor)
Vue.config.productionTip = false
Vue.use(ElementUI)
new Vue({
  store,
  router,
  render: h => h(App),
}).$mount('#app')

編寫左側(cè)導(dǎo)航

 <!-- 第二部分:導(dǎo)航欄和內(nèi)容顯示區(qū)域 -->
    <div class="main-content">
      <el-menu
        :default-active="activeMenu"
        @select="handleMenuSelect"
        background-color="#545c64"
        text-color="#fff"
        active-text-color="#ffd04b"
        :collapse="isCollapse"
      >
        <el-menu-item
          v-for="item in filteredMenuItems"
          :key="item.menuPath"
          :index="item.menuPath"
        >
          <i :class="item.menuIcon"></i>
          <span slot="title">{{ item.menuName }}</span>
        </el-menu-item>
        <el-submenu
          v-for="item in menuItemsWithChildren"
          :key="item.menuPath"
          :index="item.menuPath"
        >
          <template #title>
            <i :class="item.menuIcon"></i>
            <span slot="title">{{ item.menuName }}</span>
          </template>
          <el-menu-item
            v-for="child in item.children"
            :key="child.menuPath"
            :index="child.menuPath"
          >
            <i :class="child.menuIcon"></i>
            <span slot="title">{{ child.menuName }}</span>
          </el-menu-item>
        </el-submenu>
      </el-menu>
		//路由出口
      <div class="content">
        <router-view></router-view>
      </div>
    </div>

返回的菜單數(shù)據(jù)

菜單數(shù)據(jù)時(shí)根據(jù)用戶id請(qǐng)求后端菜單權(quán)限后返回的菜單數(shù)據(jù)

動(dòng)態(tài)導(dǎo)航

安裝vue-router、elementui步驟與靜態(tài)導(dǎo)航相同

編寫router/index.js

import Vue from "vue";
import VueRouter from "vue-router";
Vue.use(VueRouter);
const constantRoutes = [
    {
        path: "/login",
        name: "Login",
        component: () => import("@/views/Login.vue")
    },
    {
        path: "/home",
        name: "Home",
        component: () => import("@/views/Home.vue"),
        children: []
    },
    // {
    //     path: "*",
    //     name: "NotFound",
    //     component: () => import("@/views/NotFound.vue")
    // },
]
const createRouter = () => new VueRouter({
    mode: "hash",
    routes: constantRoutes
})
const router = createRouter();
//路由重置方法
export function resetRouter() {
    const newRouter = createRouter();
    router.matcher = newRouter.matcher; // 重置路由
}
//動(dòng)態(tài)加載路由方法
export const addDynamicRoutes = (menus) => {
  debugger;
  const routes = [];
  //1.轉(zhuǎn)換菜單為路由配置
  const asyncRoutes = coverMenusToRoutes1(routes,menus);
  //2. 添加嵌套路由到Home
  asyncRoutes.forEach(route => {
    // debugger;
    // if (route.name !== '') {
    //   router.addRoute("Home", route);
    // }
    router.addRoute("Home", route);
  });
}
//菜單轉(zhuǎn)換路由方法
const coverMenusToRoutes = (menus) => {
  if (!menus) return [];
  const routes = [];
  menus.forEach(menu => {
    const route = {
      path: menu.path,
      name: menu.path.slice(1),
      meta: {title: menu.name,icon: menu.icon},
      component: resolveComponent(menu.component),
    };
    if (menu.children && menu.children.length > 0) {
      route.children = coverMenusToRoutes(menu.children);
    }
    routes.push(route);
  })
  return routes;
}
const coverMenusToRoutes1 = (routes,menus) => {
  if (!menus) return [];
  // const routes = [];
  menus.forEach(menu => {
    if (menu.component.length > 0){
      const route = {
        path: menu.path,
        name: menu.path.slice(1),
        meta: {title: menu.name,icon: menu.icon},
        component: resolveComponent(menu.component),
      };
      routes.push(route);
    }
    if (menu.children && menu.children.length > 0) {
      coverMenusToRoutes1(routes,menu.children);
    }
  })
  return routes;
}
//動(dòng)態(tài)解析組件路由
function resolveComponent(component) {
  if (!component) return undefined;
  return () => import(`@/views/${component}`);
}
// 導(dǎo)航守衛(wèi)
// 使用 router.beforeEach 注冊(cè)一個(gè)全局前置守衛(wèi),判斷用戶是否登陸
router.beforeEach((to, from, next) => {
    if (to.path === '/login') {
      next();
    } else {
      let token = localStorage.getItem('token');
      if (token === null || token === '') {
        next('/login');
      } else {
        next();
      }
    }
  });
export default router;

動(dòng)態(tài)導(dǎo)航需要特別注意路徑問(wèn)題,如果路徑不正確會(huì)導(dǎo)致菜單無(wú)法正常顯示,因?yàn)樵陧?xiàng)目中返回的菜單數(shù)據(jù)時(shí)樹形結(jié)構(gòu),在處理菜單數(shù)據(jù)時(shí)如果按樹形結(jié)構(gòu)嵌套再添加到Home路由的children列表中,菜單無(wú)法正常的顯示,后面修改了處理邏輯,把有組件的菜單添加到Home路由的children列表后,菜單可以正常顯示,需要特別注意

左側(cè)菜單

通過(guò)for循環(huán)生成

<template>
  <el-menu
    :default-active="defaultActive"
    class="el-menu"
    @open="handleOpen"
    @close="handleClose"
    @select="handleSelect"
    :collapse="isCollapse"
    background-color="#545c64"
    text-color="#fff"
    active-text-color="#ffd04b"
  >
    <span><i :class="collapseClass" @click="changeMenu"></i></span>
    <template v-for="item in menuList">
      <el-submenu
        v-if="item.children && item.children.length"
        :index="item.path"
        :key="item.id"
      >
        <template slot="title">
          <i :class="item.icon"></i>
          <span slot="title">{{ item.name }}</span>
        </template>
        <template v-for="child in item.children">
          <el-submenu v-if="child.children && child.children.length" :index="child.path" :key="child.id">
            <template slot="title">
              <i :class="child.icon"></i>
              <span slot="title">{{child.name}}</span>
            </template>
            <el-menu-item v-for="ch in child.children" :index="ch.path" :key="ch.id">
              <i :class="ch.icon"></i>
              <span slot="title">{{ch.name}}</span>
            </el-menu-item>
          </el-submenu>
          <!-- v-for="child in item.children" -->
          <el-menu-item v-else
            :index="child.path"
            :key="child.id"
          >
            <i :class="child.icon"></i>
            <span slot="title">{{ child.name }}</span>
          </el-menu-item>
        </template>
      </el-submenu>
      <el-menu-item v-else :index="item.path" :key="item.id">
        <i :class="item.icon"></i>
        <span slot="title">{{ item.name }}</span>
      </el-menu-item>
    </template>
  </el-menu>
</template>
<script>
export default {
  data() {
    return {
      collapseClass: "el-icon-s-fold",
      isCollapse: false,
      defaultActive: "1-4-1",
      menuList: [],
    };
  },
  mounted() {
    //獲取動(dòng)態(tài)菜單
    this.createMenuList();
  },
  methods: {
    createMenuList() {
      console.log(this.$store.state.menus);
      this.menuList = this.$store.state.menus;
    },
    handleOpen(key, keyPath) {
      console.log(key, keyPath);
    },
    handleClose(key, keyPath) {
      console.log(key, keyPath);
    },
    changeMenu() {
      this.isCollapse = !this.isCollapse;
      if (this.isCollapse) {
        this.collapseClass = "el-icon-s-unfold";
      } else {
        this.collapseClass = "el-icon-s-fold";
      }
    },
    handleSelect(index) {
      this.activeMenu = index;
      if (this.$route.path !== index) {
        // 檢查當(dāng)前路徑是否與目標(biāo)路徑相同
        this.$router.push(index);
      }
    },
  },
};
</script>
<style>
.el-menu:not(.el-menu--collapse) {
  width: 220px;
  /* height: 100vh; */
  overflow: hidden;
}
.el-menu {
  width: 60px;
  /* height: 100vh; */
  overflow: hidden;
}
</style>

通過(guò)for循環(huán)+遞歸生成

菜單生成子組件

<template>
  <el-menu
    :default-active="defaultActive"
    class="el-menu"
    @open="handleOpen"
    @close="handleClose"
    @select="handleSelect"
    :collapse="isCollapse"
    background-color="#545c64"
    text-color="#fff"
    active-text-color="#ffd04b"
  >
    <template v-for="item in menuList">
      <el-submenu v-if="item.children && item.children.length" :index="item.path" :key="item.id">
      <template slot="title">
        <i :class="item.icon"></i>
        <span slot="title">{{item.name}}</span>
      </template>
      <!-- 遞歸調(diào)用 -->
      <AsideMenu :menuList="item.children"></AsideMenu>
    </el-submenu>
    <el-menu-item v-else :index="item.path" :key="item.id">
        <i :class="item.icon"></i>
        <span slot="title">{{item.name}}</span>
    </el-menu-item>
    </template>
  </el-menu>
</template>
<script>
export default {
  name: "AsideMenu", //name必須要有,要和遞歸調(diào)用的名稱保持一致
  components: {
  },
  props: {
    menuList: [],
    // eslint-disable-next-line vue/require-prop-type-constructor
    isCollapse: false,
  },
  data() {
    return {
      // collapseClass: "el-icon-s-fold",
      // isCollapse: false,
      defaultActive: "1-4-1",
    };
  },
  methods: {
    handleOpen(key, keyPath) {
      console.log(key, keyPath);
    },
    handleClose(key, keyPath) {
      console.log(key, keyPath);
    },
    handleSelect(index) {
      debugger;
      this.activeMenu = index;
      console.log(index);
      console.log(this.$route);
      console.log(this.$router.getRoutes());
      if (this.$route.path !== index) {
        // 檢查當(dāng)前路徑是否與目標(biāo)路徑相同
        this.$router.push(index);
      }
    },
  },
};
</script>
<style>
.el-menu:not(.el-menu--collapse) {
  width: 220px;
  /* height: 100vh; */
  overflow: hidden;
  border-right: none; /* 隱藏右側(cè)的邊框 */
}
.el-menu {
  width: 60px;
  /* height: 100vh; */
  overflow: hidden;
  border-right: none;
}
</style>

子組件名稱是必須要有的,遞歸調(diào)用時(shí)按照名稱進(jìn)行遞歸調(diào)用。在這個(gè)項(xiàng)目中子組件名稱為:AsideMenu,遞歸調(diào)用時(shí)使用 AsideMenu來(lái)引用自身

調(diào)用菜單生成的父組件

<template>
  <div class="sidebar">
    <span><i :class="collapseClass" @click="changeMenu"></i></span>
    <!-- 調(diào)用菜單生成組件 -->
     <aside-menu :menuList="menuList" :isCollapse="isCollapse"  />
  </div>
</template>
<script>
import AsideMenu from '@/components/AsideMenu.vue';
export default {
  components: {
    AsideMenu
  },
  data() {
    return {
      collapseClass: "el-icon-s-fold",
      isCollapse: false,
      menuList: []
    };
  },
  mounted() {
    //獲取動(dòng)態(tài)菜單
    this.createMenuList();
  },
  methods: {
    createMenuList() {
      console.log(this.$store.state.menus);
      this.menuList = this.$store.state.menus;
    },
    changeMenu() {
      this.isCollapse = !this.isCollapse;
      if (this.isCollapse) {
        this.collapseClass = "el-icon-s-unfold";
      } else {
        this.collapseClass = "el-icon-s-fold";
      }
    },
  }
};
</script>
<style scoped>
.sidebar {
    /* border: 1px solid red; */
    background-color:#545c64;
}
</style>

store/index.js

使用vuex保存用戶id,token,菜單列表,權(quán)限信息,角色信息

import Vue from "vue";
import vuex from "vuex";
Vue.use(vuex);
const store = new vuex.Store({
    state: {
        //用戶id
        userId: {},
        //用戶token
        token: "",
        //用戶角色
        role: "",
        //用戶權(quán)限
        permission: "",
        //用戶菜單
        menus: [],
        //用戶路由
    },
    getters: {
        //獲取用戶id
        getUserId(state) {
            return state.userId;
        },
        //獲取用戶token
        getToken(state) {
            return state.token;
        },
        //獲取用戶角色
        getRole(state) {
            return state.role;
        },
        //獲取用戶權(quán)限
        getPermission(state) {
            return state.permission;
       },
        //獲取用戶菜單
        getMenus(state) {
            return state.menus;
        },
    },
    mutations: {
        //設(shè)置用戶id
        setUserId(state, userId) {
            state.userId = userId;
            localStorage.setItem("userId", userId);
        },
        //設(shè)置用戶token
        setToken(state, token) {
            state.token = token;
            localStorage.setItem("token", token);
        },
        //設(shè)置用戶角色
        setRole(state, role) {
            state.role = role;
        },
        //設(shè)置用戶權(quán)限
        setPermission(state, permission) {
            state.permission = permission;
        },
        //設(shè)置用戶菜單
        setMenus(state, menus) {
            state.menus = menus;
            localStorage.setItem("menus", menus);
        },
    }
})
export default store;

main.js中引入store

import Vue from 'vue'
import App from './App.vue'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import router from './router'
import store from './store'
Vue.use(ElementUI)
Vue.config.productionTip = false
new Vue({
    store,
    router,
    render: h => h(App),
}).$mount('#app')

登錄頁(yè)面代碼

登錄頁(yè)面存儲(chǔ)用戶信息、菜單信息、并動(dòng)態(tài)加載路由

<!-- eslint-disable vue/multi-word-component-names -->
<template>
  <el-row type="flex" justify="center" align="middle" style="height: 100vh;">
    <el-col :xs="24" :sm="12" :md="8" :lg="6">
      <el-card class="box-card">
        <div class="clearfix">
          <img src="@/assets/logo.png" class="logo" />
          <h2>歡迎登錄</h2>
        </div>
        <el-form :model="loginForm" ref="loginForm" :rules="loginRules" label-width="100px">
          <el-form-item label="用戶名" prop="username">
            <el-input v-model="loginForm.username" prefix-icon="el-icon-user" autocomplete="off"></el-input>
          </el-form-item>
          <el-form-item label="密碼" prop="password">
            <el-input type="password" v-model="loginForm.password" prefix-icon="el-icon-lock" show-password autocomplete="off"></el-input>
          </el-form-item>
          <el-form-item>
            <el-button type="primary" @click="submitForm">登錄</el-button>
            <el-button @click="resetForm">重置</el-button>
          </el-form-item>
        </el-form>
      </el-card>
    </el-col>
  </el-row>
</template>
<script>
import { Message } from 'element-ui';
import http from '../request/http'
import { resetRouter,addDynamicRoutes } from '@/router/index'
export default {
  data() {
    return {
      loginForm: {
        username: '',
        password: ''
      },
      loginRules: {
        username: [{ required: true, message: '請(qǐng)輸入用戶名', trigger: 'blur' }],
        password: [{ required: true, message: '請(qǐng)輸入密碼', trigger: 'blur' }]
      }
    };
  },
  methods: {
    submitForm() {
      this.$refs.loginForm.validate((valid) => {
        if (valid) {
          // 這里可以添加提交到服務(wù)器的邏輯
          http.post('/user/login',this.loginForm,{
                headers: {
                  "Content-Type": "application/json;charset=UTF-8",
                },
              }).then((res) => {
            if (res.data.code === 200) {
              // 登錄成功,可以進(jìn)行后續(xù)操作,如跳轉(zhuǎn)到主頁(yè)
              //保存用戶id、token、菜單列表
              // console.log(res.data.data);
              const userId = res.data.data.user.id;
              const token = res.data.data.user.token;
              this.$store.commit('setUserId', userId);
              this.$store.commit('setToken', token);
              this.$store.commit('setMenus', res.data.data.menus);
              //創(chuàng)建動(dòng)態(tài)路由
              //1.重置路由
              resetRouter();
              //2.添加動(dòng)態(tài)路由
              const menus = res.data.data.menus;
              addDynamicRoutes(menus);
              this.$router.push('/home');
            } else {
              // 登錄失敗,可以提示錯(cuò)誤信息
              Message.error(res.msg);
            }
          });
        } else {
          console.log('表單驗(yàn)證失?。?);
          return false;
        }
      });
    },
    resetForm() {
      this.$refs.loginForm.resetFields();
    }
  }
};
</script>
<style scoped>
.box-card {
  /* border: 1px solid red; */
  width: 100%; /* 或者具體寬度 */
  border-radius: 10px; /* 圓角 */
  box-shadow: 0 0 10px rgba(0,0,0,0.1); /* 陰影 */
  background-color:aliceblue;
}
.el-row {
    background-image: url('../assets/pic01.jpg');
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
}
.logo {
  width: 80px;
  height: 80px;
}
</style>

菜單返回?cái)?shù)據(jù)

{
    "code": 200,
    "message": "請(qǐng)求成功",
    "data": {
        "menus": [
            {
                "id": "1913479834787434497",
                "parentId": null,
                "name": "系統(tǒng)管理",
                "path": "",
                "component": "",
                "perms": null,
                "type": 1,
                "icon": "el-icon-s-tools",
                "orderNum": 0,
                "visible": false,
                "createTime": null,
                "updateTime": null,
                "rf1": null,
                "rf2": null,
                "rf3": null,
                "rf4": null,
                "rf5": null,
                "children": [
                    {
                        "id": "1913484019050274818",
                        "parentId": "1913479834787434497",
                        "name": "菜單管理",
                        "path": "/menu",
                        "component": "MenuManage.vue",
                        "perms": null,
                        "type": 1,
                        "icon": "el-icon-menu",
                        "orderNum": 0,
                        "visible": false,
                        "createTime": null,
                        "updateTime": null,
                        "rf1": "系統(tǒng)管理",
                        "rf2": null,
                        "rf3": null,
                        "rf4": null,
                        "rf5": null,
                        "children": null
                    },
                    {
                        "id": "1913488214084083714",
                        "parentId": "1913479834787434497",
                        "name": "二級(jí)菜單",
                        "path": "",
                        "component": "",
                        "perms": null,
                        "type": 1,
                        "icon": "el-icon-location",
                        "orderNum": 1,
                        "visible": false,
                        "createTime": null,
                        "updateTime": null,
                        "rf1": "系統(tǒng)管理",
                        "rf2": null,
                        "rf3": null,
                        "rf4": null,
                        "rf5": null,
                        "children": [
                            {
                                "id": "1913488799369846786",
                                "parentId": "1913488214084083714",
                                "name": "三級(jí)菜單",
                                "path": "/san",
                                "component": "SanManage.vue",
                                "perms": null,
                                "type": 1,
                                "icon": "el-icon-star-on",
                                "orderNum": 0,
                                "visible": false,
                                "createTime": null,
                                "updateTime": null,
                                "rf1": "二級(jí)菜單",
                                "rf2": null,
                                "rf3": null,
                                "rf4": null,
                                "rf5": null,
                                "children": null
                            }
                        ]
                    }
                ]
            }
        ],
        "user": {
            "id": "123456",
            "username": "admin",
            "password": "$2a$10$0uPlhwgy.OlkV20pRJ/9Wu8OJ61OfbcMqMXf60qI4qsahlxJD4iUq",
            "nickname": "wangcheng",
            "avatar": null,
            "email": null,
            "mobile": null,
            "status": 1,
            "deptId": null,
            "createTime": null,
            "updateTime": null,
            "token": "eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIzMWMwOTgzNzQ2MTQ0ZGNiYmJhZTgwZmJhYzNkNWFjMSIsImlhdCI6MTc0NTE5NjAxNCwic3ViIjoiMTIzNDU2IiwiZXhwIjoxNzQ1ODAwODE0fQ.OyZaKaHRfu0PfMSubrnU1qLDOQHfisdQkTvByCMeIes",
            "roles": null
        }
    }
}

總結(jié)

項(xiàng)目開發(fā)過(guò)程中動(dòng)態(tài)菜單生成、動(dòng)態(tài)路由的正確配置是困難點(diǎn)。

動(dòng)態(tài)菜單的遞歸調(diào)用

遞歸調(diào)用最主要的是對(duì)自身的調(diào)用,要保持名稱和調(diào)用自身組件的一致性。

動(dòng)態(tài)路由

動(dòng)態(tài)路由要注意路徑問(wèn)題,不要因?yàn)椴藛畏祷貥湫谓Y(jié)構(gòu),后期處理的路由也是樹形結(jié)構(gòu),造成子路由里面多層嵌套,無(wú)法正常渲染菜單。

記錄菜單處理的另外一種方式

MenuTreeOne.vue

<template>
  <div class="custom-menu-tree">
    <template v-for="item in menuList">
      <el-submenu
        v-if="item.children && item.children.length"
        :index="item.path"
        :key="item.id"
      >
        <template slot="title">
          <i :class="item.icon"></i>
          <span slot="title">{{ item.name }}</span>
        </template>
        <!-- 遞歸調(diào)用 -->
        <AsideMenuOne :menuList="item.children"></AsideMenuOne>
      </el-submenu>
      <el-menu-item v-else :index="item.path" :key="item.id">
        <i :class="item.icon"></i>
        <span slot="title">{{ item.name }}</span>
      </el-menu-item>
    </template>
  </div>
</template>
<script>
export default {
  name: "AsideMenuOne",
  props: {
    menuList: [],
  },
  data() {
    return {};
  },
  mounted() {},
  methods: {},
};
</script>
<style scoped>
.custom-menu-tree {
  height: 100%;
  display: flex;
  flex-direction: column;
}
</style>

AsideMenuOne.vue

<template>
  <el-menu
    :default-active="defaultActive"
    class="el-menu"
    @open="handleOpen"
    @close="handleClose"
    @select="handleSelect"
    :collapse="isCollapse"
    background-color="#545c64"
    text-color="#fff"
    active-text-color="#ffd04b"
  >
    <span><i :class="collapseClass" @click="changeMenu"></i></span>
    <menu-tree-one :menuList="menuList"></menu-tree-one>
  </el-menu>
</template>
<script>
import MenuTreeOne from '@/components/MenuTreeOne.vue';
export default {
  components: { MenuTreeOne },
  data() {
    return {
      collapseClass: "el-icon-s-fold",
      isCollapse: false,
      defaultActive: "1-4-1",
      menuList: [],
    };
  },
  mounted() {
    //獲取動(dòng)態(tài)菜單
    this.createMenuList();
  },
  methods: {
    createMenuList() {
      console.log(this.$store.state.menus);
      this.menuList = this.$store.state.menus;
    },
    handleOpen(key, keyPath) {
      console.log(key, keyPath);
    },
    handleClose(key, keyPath) {
      console.log(key, keyPath);
    },
    changeMenu() {
      this.isCollapse = !this.isCollapse;
      if (this.isCollapse) {
        this.collapseClass = "el-icon-s-unfold";
      } else {
        this.collapseClass = "el-icon-s-fold";
      }
    },
    handleSelect(index) {
      this.activeMenu = index;
      if (this.$route.path !== index) {
        // 檢查當(dāng)前路徑是否與目標(biāo)路徑相同
        this.$router.push(index);
      }
    },
  },
};
</script>
<style>
.el-menu:not(.el-menu--collapse) {
  width: 220px;
  /* height: 100vh; */
  overflow: hidden;
}
.el-menu {
  width: 60px;
  /* height: 100vh; */
  overflow: hidden;
}
</style>

到此這篇關(guān)于Vue2集成ElementUI實(shí)現(xiàn)左側(cè)菜單導(dǎo)航功能的文章就介紹到這了,更多相關(guān)Vue ElementUI左側(cè)菜單導(dǎo)航內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • vue-router實(shí)現(xiàn)嵌套路由的講解

    vue-router實(shí)現(xiàn)嵌套路由的講解

    今天小編就為大家分享一篇關(guān)于vue-router實(shí)現(xiàn)嵌套路由的講解,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2019-01-01
  • vue中vue-router的使用說(shuō)明(包括在ssr中的使用)

    vue中vue-router的使用說(shuō)明(包括在ssr中的使用)

    這篇文章主要介紹了vue中vue-router的使用說(shuō)明(包括在ssr中的使用),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-05-05
  • vue動(dòng)態(tài)子組件的兩種實(shí)現(xiàn)方式

    vue動(dòng)態(tài)子組件的兩種實(shí)現(xiàn)方式

    這篇文章主要介紹了vue動(dòng)態(tài)子組件的兩種實(shí)現(xiàn)方式,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-09-09
  • 手把手教你Vue3實(shí)現(xiàn)路由跳轉(zhuǎn)

    手把手教你Vue3實(shí)現(xiàn)路由跳轉(zhuǎn)

    Vue Router是Vue.js的官方路由器,它與Vue.js核心深度集成,使使用Vue.js構(gòu)建單頁(yè)應(yīng)用程序變得輕而易舉,下面這篇文章主要給大家介紹了關(guān)于Vue3實(shí)現(xiàn)路由跳轉(zhuǎn)的相關(guān)資料,需要的朋友可以參考下
    2022-08-08
  • vue實(shí)現(xiàn)圖片下載點(diǎn)擊按鈕彈出本地窗口選擇自定義保存路徑功能

    vue實(shí)現(xiàn)圖片下載點(diǎn)擊按鈕彈出本地窗口選擇自定義保存路徑功能

    vue前端實(shí)現(xiàn)前端下載,并實(shí)現(xiàn)點(diǎn)擊按鈕彈出本地窗口,選擇自定義保存路徑,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2023-12-12
  • Vue中scrollIntoView()方法詳解與實(shí)際運(yùn)用舉例

    Vue中scrollIntoView()方法詳解與實(shí)際運(yùn)用舉例

    這篇文章主要給大家介紹了關(guān)于Vue中scrollIntoView()方法詳解與實(shí)際運(yùn)用舉例的相關(guān)資料,該scrollIntoView()方法將調(diào)用它的元素滾動(dòng)到瀏覽器窗口的可見區(qū)域,需要的朋友可以參考下
    2023-12-12
  • 如何重置vue打印變量的顯示方式

    如何重置vue打印變量的顯示方式

    這篇文章主要給大家介紹了關(guān)于如何重置vue打印變量顯示方式的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起看看吧。
    2017-12-12
  • vue進(jìn)行下載與處理二進(jìn)制流文件的方法詳解

    vue進(jìn)行下載與處理二進(jìn)制流文件的方法詳解

    這篇文章主要為大家詳細(xì)介紹了vue如何實(shí)現(xiàn)將后端返回的二進(jìn)制流進(jìn)行處理并實(shí)現(xiàn)下載,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-12-12
  • vue中window.onresize的使用解析

    vue中window.onresize的使用解析

    這篇文章主要介紹了vue中window.onresize的使用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-04-04
  • vue組件實(shí)現(xiàn)可搜索下拉框擴(kuò)展

    vue組件實(shí)現(xiàn)可搜索下拉框擴(kuò)展

    這篇文章主要為大家詳細(xì)介紹了vue組件實(shí)現(xiàn)可搜索下拉框的方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-06-06

最新評(píng)論