一、展示
二、代码
app.vue
<template>
<div id="app">
<el-container style="border: 1px solid #eee; height: 100vh">
<el-aside v-bind:width="asideWidth" style="background-color: rgb(48, 65, 86);">
<el-menu :router="true" class="el-menu-vertical-demo" style="width: 200px; border: none"
@open="handleOpen"
@close="handleClose"
@select="handleSelect"
:collapse-transition="false"
:collapse="isCollapse"
background-color="#304156"
text-color="#fff"
active-text-color="#ffd04b">
<el-menu-item index="/">
<i class="el-icon-s-home"></i>
<span slot="title">XXX系统</span>
</el-menu-item>
<el-submenu :index="item.path" v-for="(item,index) in menu" v-if="item.children!=null">
<template slot="title" v-if="item.component==='Layout' && item.children!=null">
<i :class="item.meta.icon"></i>
<span slot="title">{{item.meta.title}}</span>
</template>
<el-menu-item-group v-if="item.children!=null">
<el-menu-item :index="c.component" v-for="(c,i) in item.children"
v-if="c.component!=='ParentView'">
<i :class="c.meta.icon"></i>{{c.meta.title}}
</el-menu-item>
</el-menu-item-group>
<el-submenu :index="p.path" v-for="(p,i) in item.children" v-if="p.component==='ParentView'">
<span slot="title">{{p.meta.title}}</span>
<el-menu-item :index="c.component" v-for="(c,i) in p.children">{{c.meta.title}}
</el-menu-item>
</el-submenu>
</el-submenu>
<el-menu-item :index="item.path" v-for="(item,index) in menu" v-if="item.children==null">
<i :class="item.meta.icon"></i>
<span slot="title">{{item.meta.title}}</span>
</el-menu-item>
</el-menu>
</el-aside>
<el-container>
<el-header style="font-size: 12px;background-color:#FFFFFF; padding: 0;height: auto">
<el-row style="-webkit-box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08); box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08); ">
<el-col :xs="1" :sm="1" :md="1" :lg="1" :xl="1" style="text-align: left;">
<span v-on:click="launch"><i style="font-size: 25px;line-height: 60px"
:class="launchIcon"></i></span>
</el-col>
<el-col :xs="19" :sm="19" :md="19" :lg="18" :xl="19">
<el-breadcrumb separator="/" style="line-height: 60px;">
<el-breadcrumb-item v-for="(item,index) in thisBreadcrumb">
<a :href="item.path">{{item.title}}</a>
</el-breadcrumb-item>
</el-breadcrumb>
</el-col>
<el-col :xs="4" :sm="4" :md="4" :lg="4" :xl="4" style="text-align: right;">
<span>王小虎</span>
<el-dropdown>
<i class="el-icon-setting" style="margin-left: 15px"></i>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item>查看</el-dropdown-item>
<el-dropdown-item>新增</el-dropdown-item>
<el-dropdown-item>删除</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</el-col>
</el-row>
<el-row style="padding: 3px 0;border-bottom: 1px solid #d8dce5;
-webkit-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 0 3px 0 rgba(0, 0, 0, 0.04);
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 0 3px 0 rgba(0, 0, 0, 0.04);">
<div style="line-height: 0">
<el-tag style="border-radius: 0;margin-left: 10px;"
key="1"
closable
:disable-transitions="true"
type=""
effect="dark"
@close="handleCloseTag(1)">
首页
</el-tag>
<el-tag style="margin-left: 15px;border-radius: 0;"
key="2"
closable
:disable-transitions="true"
type="info"
@close="handleCloseTag(2)">
关于
</el-tag>
</div>
</el-row>
</el-header>
<el-main>
<router-view/>
</el-main>
</el-container>
</el-container>
</div>
</template>
<style>
.el-header {
background-color: #B3C0D1;
color: #333;
line-height: 60px;
}
.el-aside {
color: #333;
}
a {
color: #FFFFFF;
text-decoration: none
}
body{
padding: 0;
margin: 0;
}
</style>
<script>
export default {
data() {
//这个对象一般从后端获取,菜单会存在数据库,动态获取
const menuObj = [
{
"name": "System",
"path": "/system",
"hidden": false,
"redirect": "noRedirect",
"component": "Layout",
"alwaysShow": true,
"meta": {
"title": "系统管理",
"icon": "el-icon-s-tools",
"noCache": false,
"link": null
},
"children": [
{
"name": "User",
"path": "user",
"hidden": false,
"component": "system/user/index",
"meta": {
"title": "用户管理",
"icon": "el-icon-s-check",
"noCache": false,
"link": null
}
},
{
"name": "Role",
"path": "role",
"hidden": false,
"component": "system/role/index",
"meta": {
"title": "角色管理",
"icon": "peoples",
"noCache": false,
"link": null
}
},
{
"name": "Menu",
"path": "menu",
"hidden": false,
"component": "system/menu/index",
"meta": {
"title": "菜单管理",
"icon": "tree-table",
"noCache": false,
"link": null
}
},
{
"name": "Dept",
"path": "dept",
"hidden": false,
"component": "system/dept/index",
"meta": {
"title": "部门管理",
"icon": "tree",
"noCache": false,
"link": null
}
},
{
"name": "Post",
"path": "post",
"hidden": false,
"component": "system/post/index",
"meta": {
"title": "岗位管理",
"icon": "post",
"noCache": false,
"link": null
}
},
{
"name": "Dict",
"path": "dict",
"hidden": false,
"component": "system/dict/index",
"meta": {
"title": "字典管理",
"icon": "dict",
"noCache": false,
"link": null
}
},
{
"name": "Config",
"path": "config",
"hidden": false,
"component": "system/config/index",
"meta": {
"title": "参数设置",
"icon": "edit",
"noCache": false,
"link": null
}
},
{
"name": "Notice",
"path": "notice",
"hidden": false,
"component": "system/notice/index",
"meta": {
"title": "通知公告",
"icon": "message",
"noCache": false,
"link": null
}
},
{
"name": "Log",
"path": "log",
"hidden": false,
"redirect": "noRedirect",
"component": "ParentView",
"alwaysShow": true,
"meta": {
"title": "日志管理",
"icon": "log",
"noCache": false,
"link": null
},
"children": [
{
"name": "Operlog",
"path": "operlog",
"hidden": false,
"component": "monitor/operlog/index",
"meta": {
"title": "操作日志",
"icon": "form",
"noCache": false,
"link": null
}
},
{
"name": "Logininfor",
"path": "logininfor",
"hidden": false,
"component": "monitor/logininfor/index",
"meta": {
"title": "登录日志",
"icon": "logininfor",
"noCache": false,
"link": null
}
}
]
}
]
},
{
"name": "Http://ruoyi.vip",
"path": "/about",
"hidden": false,
"component": "Layout",
"meta": {
"title": "关于",
"icon": "el-icon-question",
"noCache": false,
"link": "http://ruoyi.vip"
}
}
]
return {
pathMap: {},
thisBreadcrumb: [{"path": "/", "title": "首页"}],
menu: menuObj,
isCollapse: false,
asideWidth: '200px',
launchIcon: 'el-icon-s-fold'
}
},
methods: {
handleOpen(key, keyPath) {
// console.log(key, keyPath);
},
handleClose(key, keyPath) {
// console.log(key, keyPath);
},
handleSelect(key, keyPath) {
// console.log(key, keyPath);
this.thisBreadcrumb =[{"path": "/", "title": "首页"}]
if (keyPath.length > 0) {
const f = keyPath[0]
const e = keyPath[keyPath.length - 1]
// console.log(this.pathMap.get(f).get(e))
const paths = this.pathMap.get(f).get(e)
paths.forEach((path => {
let item = {}
item.path = '/'
item.title = path
this.thisBreadcrumb.push(item)
}))
}
},
//展开左侧导航
launch() {
if (this.isCollapse) {
//展开
this.isCollapse = false;
this.asideWidth = '200px'
this.launchIcon = 'el-icon-s-fold'
} else {
//收起
this.isCollapse = true;
this.asideWidth = '64px'
this.launchIcon = 'el-icon-s-unfold'
}
},
handleCloseTag(tag) {
console.log(tag)
},
filterMenuPaths(menu, map, fatherPaths) {
//有children
// console.log("e->" + fatherPaths)
// if (menu.component==='Layout'){
//
// }
let paths = []
if (menu.children != null && menu.children.length >= 1) {
menu.children.forEach((el) => {
let fatherNow = [];
fatherNow = fatherNow.concat(fatherPaths)
fatherNow.push(menu.meta.title)
this.filterMenuPaths(el, map, fatherNow)
})
} else { //没有有children
paths = paths.concat(fatherPaths)
paths.push(menu.meta.title)
map.set(menu.component, paths)
}
}
},
created: function () {
this.pathMap = new Map();
this.menu.forEach((m, index) => {
let map = new Map();
this.filterMenuPaths(m, map, [])
this.pathMap.set(m.path, map)
})
}
};
</script>
router
import Vue from 'vue'
import VueRouter from 'vue-router'
import HomeView from '../views/HomeView.vue'
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'home',
//组件自己创建
component: HomeView
},
{
path: '/about',
name: 'about',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: function () {
//视图自己创建
return import(/* webpackChunkName: "about" */ '../views/AboutView.vue')
}
}
]
const router = new VueRouter({
routes
})
export default router