Vue2集成ElementUI實(shí)現(xiàn)左側(cè)菜單導(dǎo)航功能
簡(jiǎn)介
在開(kāi)發(fā)后臺(tái)系統(tǒng)時(shí),通過(guò)菜單進(jìn)行導(dǎo)航是非常重要的一件事情,在前端開(kāi)發(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
編寫(xiě)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')編寫(xiě)左側(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)航相同
編寫(xiě)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í)樹(shù)形結(jié)構(gòu),在處理菜單數(shù)據(jù)時(shí)如果按樹(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)目開(kāi)發(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)椴藛畏祷貥?shù)形結(jié)構(gòu),后期處理的路由也是樹(shù)形結(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)嵌套路由的講解
今天小編就為大家分享一篇關(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中的使用),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-05-05
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)
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)前端下載,并實(shí)現(xiàn)點(diǎn)擊按鈕彈出本地窗口,選擇自定義保存路徑,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2023-12-12
Vue中scrollIntoView()方法詳解與實(shí)際運(yùn)用舉例
這篇文章主要給大家介紹了關(guān)于Vue中scrollIntoView()方法詳解與實(shí)際運(yùn)用舉例的相關(guān)資料,該scrollIntoView()方法將調(diào)用它的元素滾動(dòng)到瀏覽器窗口的可見(jiàn)區(qū)域,需要的朋友可以參考下2023-12-12
vue進(jìn)行下載與處理二進(jìn)制流文件的方法詳解
這篇文章主要為大家詳細(xì)介紹了vue如何實(shí)現(xiàn)將后端返回的二進(jìn)制流進(jìn)行處理并實(shí)現(xiàn)下載,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-12-12
vue組件實(shí)現(xiàn)可搜索下拉框擴(kuò)展
這篇文章主要為大家詳細(xì)介紹了vue組件實(shí)現(xiàn)可搜索下拉框的方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-06-06

