1. SideBar下的组件
2. index.vue 页面内容
<template>
<div class="asideNav">
<!-- 如果不要Logo可以删除此代码 -->
<Logo v-if="showLogo" :collapse="isCollapse"></Logo>
<!--
default-active:活动菜单颜色
collapse:侧边栏隐藏
background-color: 背景颜色
text-color:菜单中文本颜色
unique-opened: 是否唯一打开
active-text-colo: 活动文本颜色
collapse-transition: 隐藏过渡
mode="vertical":绑定变量
-->
<el-menu
:default-active="activeMenu"
class="el-menu-vertical"
:collapse="isCollapse"
unique-opened
active-text-color="#FFC000"
background-color="#000000"
text-color="skyblue"
mode="vertical"
>
<sidebar-item
v-for="route in routes" :key="route.path" :item="route" :base-path="route.path" />
</el-menu>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
import Logo from './Logo'
import SidebarItem from './SidebarItem'
export default {
data() {
return {};
},
components: { SidebarItem, Logo },
computed: {
...mapGetters([
'sidebar'
]),
routes() {
return this.$router.options.routes;
},
activeMenu() {
// 获取当前路由对象
const route = this.$route;
// 获取meta对象 和路径对象
const { meta, path } = route;
// 如果设置路径,侧栏将突出显示您设置的路径
if (meta.activeMenu) {
return meta.activeMenu;
}
return path;
},
// 显示logo
showLogo() {
return this.$store.state.settings.sidebarLogo;
},
// 是否关闭侧边栏
isCollapse() {
return !this.sidebar.opened
}
},
};
</script>
<style lang='scss' scoped>
.asideNav {
text-align: left;
}
/*加快侧边栏文字消失的速度*/
.el-menu {
transition: all 10ms;
}
</style>
3. Item.vue 页面内容
<script>
export default {
name: 'MenuItem',
functional: true,
props: {
icon: {
type: String,
default: ''
},
title: {
type: String,
default: ''
}
},
render(h, context) {
const { icon, title } = context.props
const vnodes = []
if (icon) {
if (icon.includes('el-icon')) {
vnodes.push(<i class={[icon, 'sub-el-icon']} />)
} else {
vnodes.push(<svg-icon icon-class={icon}/>)
}
}
if (title) {
vnodes.push(<span slot='title'>{(title)}</span>)
}
return vnodes
}
}
</script>
<style scoped>
.sub-el-icon {
color: currentColor;
width: 1em;
height: 1em;
}
</style>
4. Link.vue 页面内容
<template>
<component :is="type" v-bind="linkProps(to)">
<slot />
</component>
</template>
<script>
import { isExternal } from '@/utils/validate'
export default {
props: {
to: {
type: String,
required: true
}
},
computed: {
isExternal() {
return isExternal(this.to)
},
type() {
if (this.isExternal) {
return 'a'
}
return 'router-link'
}
},
methods: {
linkProps(to) {
if (this.isExternal) {
return {
href: to,
target: '_blank',
rel: 'noopener'
}
}
return {
to: to
}
}
}
}
</script>
5. Logo.vue 页面内容
<template>
<div class="sidebar-logo-container" :class="{'collapse':collapse}">
<transition name="sidebarLogoFade">
<router-link v-if="collapse" key="collapse" class="sidebar-logo-link" to="/">
<img v-if="logo" :src="logos" class="sidebar-logos">
</router-link>
<router-link v-else key="expand" class="sidebar-logo-link" to="/">
<img v-if="logo" :src="logo" class="sidebar-logo">
</router-link>
</transition>
</div>
</template>
<script>
export default {
name: 'SidebarLogo',
props: {
collapse: {
type: Boolean,
required: true
}
},
data() {
return {
title: '',
logo: require('@/assets/logo.png'),
logos: require('@/assets/do.png')
}
}
}
</script>
<style lang="scss" scoped>
.sidebarLogoFade-enter-active {
transition: opacity 1.5s;
}
.sidebarLogoFade-enter,
.sidebarLogoFade-leave-to {
opacity: 0;
}
.sidebar-logo-container {
position: relative;
width: 100%;
height: 60px;
line-height: 60px;
background: #171717;
text-align: center;
overflow: hidden;
& .sidebar-logo-link {
height: 100%;
width: 100%;
& .sidebar-logo {
vertical-align: middle;
margin-right: 12px;
}
& .sidebar-logos {
width: 32px;
height: 32px;
vertical-align: middle;
}
& .sidebar-title {
display: inline-block;
margin: 0;
color: #fff;
font-weight: 600;
line-height: 50px;
font-size: 14px;
font-family: Avenir, Helvetica Neue, Arial, Helvetica, sans-serif;
vertical-align: middle;
}
}
&.collapse {
.sidebar-logo {
margin-right: 0px;
}
}
}
</style>
6. SidebarItem.vue 页面内容
<template>
<div v-if="!item.hidden">
<template v-if="hasOneShowingChild(item.children,item) && (!onlyOneChild.children||onlyOneChild.noShowingChildren)&&!item.alwaysShow">
<app-link v-if="onlyOneChild.meta" :to="resolvePath(onlyOneChild.path)">
<el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{'submenu-title-noDropdown':!isNest}">
<item :icon="onlyOneChild.meta.icon||(item.meta&&item.meta.icon)" :title="onlyOneChild.meta.title" />
</el-menu-item>
</app-link>
</template>
<el-submenu v-else ref="subMenu" :index="resolvePath(item.path)" popper-append-to-body>
<template slot="title">
<item v-if="item.meta" :icon="item.meta && item.meta.icon" :title="item.meta.title" />
</template>
<sidebar-item
v-for="child in item.children"
:key="child.path"
:is-nest="true"
:item="child"
:base-path="resolvePath(child.path)"
class="nest-menu"
/>
</el-submenu>
</div>
</template>
<script>
import path from 'path' // 导入路径
import { isExternal } from '@/utils/validate' // 用于判断是外部的路径
import Item from './Item' // 迭代icon与title
import AppLink from './Link' // 应用关联 用于切换外部链接显示方法
// import FixiOSBug from './FixiOSBug' // 用于修复IOS设备鼠标离开bug
export default {
name: 'SidebarItem',
components: { Item, AppLink },
// mixins: [FixiOSBug],
props: {
// route object 路由对象
item: {
type: Object,
required: true
},
// 是否嵌套
isNest: {
type: Boolean,
default: false
},
// 基本路径
basePath: {
type: String,
default: ''
}
},
data() {
// To fix https://github.com/PanJiaChen/vue-admin-template/issues/237
// TODO: 渲染函数重构
this.onlyOneChild = null
return {}
},
methods: {
// 有一个子路由
hasOneShowingChild(children = [], parent) {
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
},
// 解析路径
resolvePath(routePath) {
// 判断是否是外部的路径
if (isExternal(routePath)) {
return routePath
}
if (isExternal(this.basePath)) {
return this.basePath
}
// 返回当前也解析好的路径
return path.resolve(this.basePath, routePath)
}
}
}
</script>
<style lang="scss">
.el-menu--collapse .el-submenu__title span{
display: none;
}
/*隐藏 > */
.el-menu--collapse .el-submenu__title .el-submenu__icon-arrow{
display: none;
}
</style>
Main.vue 页面内容(此二级路由不包含在Sidebar文件下)
<template>
<section class="app-main">
<transition name="fade-transform" mode="out-in">
<router-view :key="key" />
</transition>
</section>
</template>
<script>
export default {
name: 'AppMain',
computed: {
key() {
return this.$route.path
}
}
}
</script>
<style scoped>
.app-main {
/*50 = navbar */
height: 100%;
width: 100%;
position: relative;
overflow: auto;
}
.fixed-header+.app-main {
padding-top: 50px;
}
</style>
<style lang="scss">
// fix css style bug in open el-dialog
.el-popup-parent--hidden {
.fixed-header {
padding-right: 15px;
}
}
</style>
此时页面样式