背景:用element实现一个动态菜单,支持多层级菜单
页面布局:layout文件夹
layout.vue(菜单入口)
side-bar.vue
compomne.vue 右侧视图组件, 支持 路由 iframe切换
1.layout.vue代码
<template>
<template>
<div class="layout">
<el-header>海外主题管理台 <span><i v-if="isCollapse"
class="el-icon-s-unfold"
@click="isCollapse = false"></i><i class="el-icon-s-fold"
v-else
@click="isCollapse = true"></i></span></el-header>
<el-container>
<div :class="isCollapse ? 'left-content-colse' : 'left-content'">
<el-aside style="width:225px">
<el-scrollbar style="height:100%">
<el-menu class="el-menu-vertical-demo"
:default-active="componentId"
@open="handleOpen"
@close="handleClose"
:collapse-transition="false"
:unique-opened="true"
:collapse="isCollapse">
<side-bar :list="menuList"
@onActive="onActive"
:isCollapse="isCollapse"></side-bar>
</el-menu>
</el-scrollbar>
</el-aside>
</div>
<el-main>
<Components :componentId="componentId"></Components>
</el-main>
</el-container>
</div>
</template>
<script>
import { sideBarData } from './menuConfig'
import SideBar from './side-bar.vue'
import Components from './components.vue'
import { mapGetters } from "vuex";
export default {
components: { SideBar, Components },
data() {
return {
componentId: '1-1',
isCollapse: false,
menuList: sideBarData
};
},
methods: {
onActive(item) {
this.componentId = item.id
this.$store.commit("saveActiveMenuId", this.componentId);
},
handleOpen(key, keyPath) {
console.log(key, keyPath, '1111');
},
handleClose(key, keyPath) {
console.log(key, keyPath);
},
},
watch: {},
computed: {
...mapGetters(["activeMenuId"]),
},
created() {
if (this.activeMenuId) this.componentId = this.activeMenuId;
},
mounted() { },
};
</script>
<style lang="less" scoped>
.layout {
position: absolute;
top: 0;
left: 0;
width: 100vw;
height: 100%;
overflow: hidden;
}
.left-content {
height: 100vh;
overflow: hidden;
}
.left-content-colse {
width: 64px;
height: 100vh;
background: red;
overflow: hidden;
}
.el-submenu__title {
span {
display: inline-block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
</style>
<style>
.el-header {
background-color: #008dff;
color: #fff;
font-size: 18px;
height: auto;
line-height: 60px;
}
.el-menu {
background-color: #13254a;
border-right: none;
color: #fff;
}
.el-submenu__title {
color: #fff;
z-index: 9 !important;
}
.el-menu-item {
color: #fff;
border-color: none;
}
.el-aside {
background-color: #13254a;
height: 100%;
color: #fff;
transition: width 0.5s;
}
.el-submenu__title:hover {
color: #fff;
background-color: rgb(0, 141, 255, 0.2) !important;
}
.el-menu-item:hover {
color: #fff;
background-color: rgb(0, 141, 255, 0.2) !important;
}
.el-menu-item.is-active {
color: #fff;
background-color: #008dff !important;
}
.el-main {
background-color: #e9eef3;
color: #333;
}
.el-icon-menu:before {
content: "\e798";
color: #fff;
}
/*
.el-menu-vertical-demo:not(.el-menu--collapse) {
width: 200px;
min-height: 400px;
} */
</style>
2.side-bar.vue 代码
<template>
<fragment>
<template v-for="(item,index) in list">
<!-- 标题 -->
<template v-if="item.children && item.children.length">
<el-submenu :key="index"
:index="item.id"
@click="onClick(item)">
<template :index="item.id"
slot="title">
<i :class="item.icon"
style="color:#fff"></i>
<span slot="title">{{item.name}}</span>
</template>
<el-menu-item-group>
<sideBar :list="item.children"
v-bind="$attrs"
v-on="$listeners"></sideBar>
</el-menu-item-group>
</el-submenu>
</template>
<!-- 选项 -->
<template v-else>
<el-menu-item :key="index"
@click="onClick(item)"
:index="item.id">
<i :class="item.icon"></i>
<!-- <router-link :to="item.path">{{item.name}}</router-link> -->
<span slot="title">{{item.name}}</span>
</el-menu-item>
</template>
</template>
</fragment>
</template>
<script>
export default {
name: "sideBar",
props: {
list: Array,
isCollapse: Boolean
},
created() {
},
methods: {
onClick(val) {
this.$emit('onActive', val)
}
}
};
</script>
<style></style>
3.components.vue代码
<template>
<div class="box"
v-loading="loading">
<template>
<iframe id="myIframe"
:src="path"
frameborder="0"></iframe>
</template>
<template>
<router-view></router-view>
</template>
</div>
</template>
<script>
import { sideBarData } from './menuConfig'
export default {
name: "components",
props: {
componentId: String,
list: Array,
},
watch: {
componentId: {
handler(val) {
if (val) {
this.loading = true;
this.getNode(this.menuList, val);
}
},
immediate: true
}
},
data() {
return {
loading: true,
currentView: 'wallpaper-approve',
menuList: sideBarData,
activeNode: {},
path: '',
};
},
methods: {
// 递归获取节点
getNode(dataList, val) {
if (dataList.length > 0) {
dataList.forEach(item => {
if (item.children) {
this.getNode(item.children, val)
} else {
if (item.id === val) {
this.activeNode = item;
}
}
})
}
this.path = this.activeNode.url;
console.log('this.activeNode', this.activeNode)
},
changeviewFun(val) {
this.currentView = val;
}
},
mounted() {
let self = this
var iframe = document.getElementById('myIframe');
if (!/*@cc_on!@*/0) { //if not IE
iframe.onload = function () {
self.loading = false
};
} else {
iframe.onreadystatechange = function () {
if (iframe.readyState == "complete") {
self.loading = false
}
};
}
}
};
</script>
<style>
.box {
width: 100%;
height: calc(100% - 60px);
}
.el-main {
background-color: #f0f2f5 !important;
color: #f0f2f5;
}
iframe {
width: 100%;
height: 100%;
/* background: red !important; */
}
</style>
4.配置文件
{
id:'1',
name:'一级目录',
icon: "el-icon-menu",
type:'', // 1路由 或 2 iframe
children: [
{
id: '1-1',
name:'二级目录',
type:'2',
path:'xxx',
url: `${BASE_URL}/xxx`
},
]
},
5. 动态加载菜单收缩字体不显示问题main.js
collapse-transition
// main.js
import Fragment from ‘vue-fragment’
Vue.use(Fragment.Plugin)
参考:Vue-Components-Library/SidebarItem.vue at master · NLRX-WJC/Vue-Components-Library · GitHub
网友评论