修改侧边栏的样式

master
toesbieya 6 years ago
parent a8d317ac9f
commit 12770dcaf7
  1. 74
      vue/element-ui-personal/components/Menu/MenuItem.vue
  2. 278
      vue/element-ui-personal/components/Menu/Submenu.vue
  3. 4
      vue/element-ui-personal/index.js
  4. 2
      vue/element-ui-personal/mixins/vue-popper.js
  5. 20
      vue/src/assets/styles/variables.scss
  6. 3
      vue/src/components/ContextMenu/index.vue
  7. 20
      vue/src/layout/components/Sidebar/components/SidebarItem.vue
  8. 4
      vue/src/layout/components/Sidebar/index.vue
  9. 71
      vue/src/layout/components/Sidebar/style.scss

@ -0,0 +1,74 @@
<template>
<li
class="el-menu-item"
:style="paddingStyle"
:class="{'is-active': active,'is-disabled': disabled}"
@click="handleClick"
>
<el-tooltip
v-if="parentMenu.$options.componentName === 'ElMenu' && rootMenu.collapse && $slots.title"
effect="dark"
placement="right"
>
<div slot="content">
<slot name="title"/>
</div>
<div style="position: absolute;left: 0;top: 0;height: 100%;width: 100%;display: inline-block;box-sizing: border-box;padding: 0 20px;">
<slot/>
</div>
</el-tooltip>
<template v-else>
<slot/>
<slot name="title"/>
</template>
</li>
</template>
<script>
import MenuMixin from 'element-ui/packages/menu/src/menu-mixin'
import Emitter from 'element-ui/lib/mixins/emitter'
export default {
name: 'ElMenuItem',
componentName: 'ElMenuItem',
mixins: [MenuMixin, Emitter],
data() {
return {}
},
props: {
index: String,
route: [String, Object],
disabled: Boolean
},
computed: {
active() {
return this.index === this.rootMenu.activeIndex
}
},
methods: {
handleClick() {
if (!this.disabled) {
this.dispatch('ElMenu', 'item-click', this)
this.$emit('click', this)
}
}
},
mounted() {
this.parentMenu.addItem(this)
this.rootMenu.addItem(this)
},
beforeDestroy() {
this.parentMenu.removeItem(this)
this.rootMenu.removeItem(this)
}
}
</script>

@ -0,0 +1,278 @@
<script type="text/jsx">
import MenuMixin from 'element-ui/packages/menu/src/menu-mixin'
import Emitter from 'element-ui/lib/mixins/emitter'
import Popper from 'element-ui/lib/utils/vue-popper'
const PopperMixins = {
props: {
transformOrigin: {type: [Boolean, String], default: false},
offset: Popper.props.offset,
boundariesPadding: Popper.props.boundariesPadding,
popperOptions: Popper.props.popperOptions
},
data: Popper.data,
methods: Popper.methods,
beforeDestroy: Popper.beforeDestroy,
deactivated: Popper.deactivated
}
export default {
name: 'ElSubmenu',
componentName: 'ElSubmenu',
mixins: [MenuMixin, Emitter, PopperMixins],
props: {
index: String,
showTimeout: {type: Number, default: 300},
hideTimeout: {type: Number, default: 300},
popperClass: String,
disabled: Boolean,
popperAppendToBody: {type: Boolean, default: true}
},
data() {
return {
popperJS: null,
timeout: null,
items: {},
submenus: {},
mouseInChild: false
}
},
computed: {
appendToBody() {
return this.popperAppendToBody === undefined
? this.isFirstLevel
: this.popperAppendToBody
},
menuTransitionName() {
return this.rootMenu.collapse ? 'el-zoom-in-left' : 'el-zoom-in-top'
},
opened() {
return this.rootMenu.openedMenus.includes(this.index)
},
active() {
const items = this.items
const isActive = Object.keys(items).some(key => items[key].active)
if (!isActive) {
const submenus = this.submenus
return Object.keys(submenus).some(key => submenus[key].active)
}
return isActive
},
mode() {
return this.rootMenu.mode
},
isMenuPopup() {
return this.rootMenu.isMenuPopup
},
isFirstLevel() {
const arr = ['ElSubmenu', 'ElMenuItemGroup']
let isFirstLevel = true
let parent = this.$parent
while (parent && parent !== this.rootMenu) {
if (arr.includes(parent.$options.componentName)) {
isFirstLevel = false
break
}
else parent = parent.$parent
}
return isFirstLevel
}
},
watch: {
opened() {
this.isMenuPopup && this.$nextTick(this.updatePopper)
}
},
methods: {
handleCollapseToggle(value) {
if (value) {
this.initPopper()
}
else {
this.doDestroy()
}
},
addItem(item) {
this.$set(this.items, item.index, item)
},
removeItem(item) {
delete this.items[item.index]
},
addSubmenu(item) {
this.$set(this.submenus, item.index, item)
},
removeSubmenu(item) {
delete this.submenus[item.index]
},
handleClick() {
const {rootMenu, disabled} = this
if (
(rootMenu.menuTrigger === 'hover' && rootMenu.mode === 'horizontal') ||
(rootMenu.collapse && rootMenu.mode === 'vertical') ||
disabled
) {
return
}
this.dispatch('ElMenu', 'submenu-click', this)
},
handleMouseenter(event, showTimeout = this.showTimeout) {
if (!('ActiveXObject' in window) && event.type === 'focus' && !event.relatedTarget) {
return
}
const {rootMenu, disabled} = this
if (
(rootMenu.menuTrigger === 'click' && rootMenu.mode === 'horizontal') ||
(!rootMenu.collapse && rootMenu.mode === 'vertical') ||
disabled
) {
return
}
this.dispatch('ElSubmenu', 'mouse-enter-child')
clearTimeout(this.timeout)
this.timeout = setTimeout(() => {
this.rootMenu.openMenu(this.index, this.indexPath)
}, showTimeout)
if (this.appendToBody) {
this.$parent.$el.dispatchEvent(new MouseEvent('mouseenter'))
}
},
handleMouseleave(deepDispatch = false) {
const {rootMenu} = this
if (
(rootMenu.menuTrigger === 'click' && rootMenu.mode === 'horizontal') ||
(!rootMenu.collapse && rootMenu.mode === 'vertical')
) {
return
}
this.dispatch('ElSubmenu', 'mouse-leave-child')
clearTimeout(this.timeout)
this.timeout = setTimeout(() => {
!this.mouseInChild && this.rootMenu.closeMenu(this.index)
}, this.hideTimeout)
if (this.appendToBody && deepDispatch) {
if (this.$parent.$options.name === 'ElSubmenu') {
this.$parent.handleMouseleave(true)
}
}
},
updatePlacement() {
this.placement = this.mode === 'horizontal' && this.isFirstLevel
? 'bottom-start'
: 'right-start'
},
initPopper() {
this.referenceElm = this.$el
this.popperElm = this.$refs.menu
this.updatePlacement()
}
},
created() {
this.$on('toggle-collapse', this.handleCollapseToggle)
this.$on('mouse-enter-child', () => {
this.mouseInChild = true
clearTimeout(this.timeout)
})
this.$on('mouse-leave-child', () => {
this.mouseInChild = false
clearTimeout(this.timeout)
})
},
mounted() {
this.parentMenu.addSubmenu(this)
this.rootMenu.addSubmenu(this)
this.initPopper()
},
beforeDestroy() {
this.parentMenu.removeSubmenu(this)
this.rootMenu.removeSubmenu(this)
},
render() {
const {rootMenu, $slots} = this
const popupMenu = (
<transition name={this.menuTransitionName}>
<div
ref="menu"
v-show={this.opened}
class={[`el-menu--${this.mode}`, this.popperClass]}
on-mouseenter={e => this.handleMouseenter(e, 100)}
on-mouseleave={() => this.handleMouseleave(true)}
on-focus={e => this.handleMouseenter(e, 100)}>
<ul class={['el-menu el-menu--popup', `el-menu--popup-${this.currentPlacement}`]}>
{$slots.default}
</ul>
</div>
</transition>
)
const inlineMenu = (
<el-collapse-transition>
<ul v-show={this.opened} class="el-menu el-menu--inline">
{$slots.default}
</ul>
</el-collapse-transition>
)
const submenuTitleIcon = (
rootMenu.mode === 'horizontal' && this.isFirstLevel ||
rootMenu.mode === 'vertical' && !rootMenu.collapse
) ? 'el-icon-arrow-down' : 'el-icon-arrow-right'
return (
<li
class={{
'el-submenu': true,
'is-active': this.active,
'is-opened': this.opened,
'is-disabled': this.disabled
}}
on-mouseenter={this.handleMouseenter}
on-mouseleave={() => this.handleMouseleave(false)}
on-focus={this.handleMouseenter}
>
<div
ref="submenu-title"
class="el-submenu__title"
style={this.paddingStyle}
on-click={this.handleClick}
>
{$slots.title}
<i class={['el-submenu__icon-arrow', submenuTitleIcon]}/>
</div>
{this.isMenuPopup ? popupMenu : inlineMenu}
</li>
)
}
}
</script>
<style>
</style>

@ -1,7 +1,9 @@
import MenuItem from "./components/Menu/MenuItem"
import Submenu from "./components/Menu/Submenu"
import Message from "./components/Message" import Message from "./components/Message"
import Select from './components/Select/Select' import Select from './components/Select/Select'
const components = [Select] const components = [MenuItem, Submenu, Select]
export default function (Vue) { export default function (Vue) {
components.forEach(component => { components.forEach(component => {

@ -43,7 +43,7 @@ export default {
this.showPopper = val this.showPopper = val
this.$emit('input', val) this.$emit('input', val)
if (this.disabled) return if (this.disabled) return
val && this.updatePopper() val ? this.updatePopper() : this.destroyPopper()
} }
} }
}, },

@ -36,16 +36,19 @@ $--color-info: $--color-teal;
} }
} }
// sidebar //el-sub-menu的背景色
$menu-text-color: #D6E2F0;
$menu-active-text-color: $--color-primary;
$menu-background: #304156;
$menu-hover: #263445;
$sub-menu-background: #1f2d3d; $sub-menu-background: #1f2d3d;
$sub-menu-hover: #001528; //覆盖el-menu的背景色
$--menu-background-color: #304156;
//覆盖el-menu的文字颜色
$--menu-item-font-color: hsla(0, 0%, 99.6%, .65);
//el-menu的文字hover颜色
$--menu-item-hover-color: #fefefe;
//覆盖el-menu的文字hover背景颜色
$--menu-item-hover-fill: none;
//侧边栏宽度 //侧边栏宽度
$side-bar-width: 210px; $side-bar-width: 256px;
//头部导航栏高度 //头部导航栏高度
$nav-height: 50px; $nav-height: 50px;
//头部多页签栏高度 //头部多页签栏高度
@ -60,9 +63,6 @@ $--font-path: '~element-ui/lib/theme-chalk/fonts';
// the :export directive is the magic sauce for webpack // the :export directive is the magic sauce for webpack
// https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass // https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass
:export { :export {
menu-text-color: $menu-text-color;
menu-active-text-color: $menu-active-text-color;
menu-background: $menu-background;
primary: $--color-primary; primary: $--color-primary;
info: $--color-info; info: $--color-info;
success: $--color-success; success: $--color-success;

@ -67,7 +67,7 @@
.contextmenu { .contextmenu {
margin: 0; margin: 0;
background: $menu-background; background: $--menu-background-color;
z-index: 10; z-index: 10;
position: absolute; position: absolute;
list-style-type: none; list-style-type: none;
@ -84,7 +84,6 @@
cursor: pointer; cursor: pointer;
&:hover { &:hover {
background: $menu-hover;
color: $--color-primary; color: $--color-primary;
} }
} }

@ -11,7 +11,7 @@
return null return null
} }
function renderNode(h, {item, isNest, showParent, collapse}) { function renderNode(h, {item, showParent, collapse}) {
let onlyOneChild = getOnlyChild(item) let onlyOneChild = getOnlyChild(item)
const showSingle = onlyOneChild && !onlyOneChild.children const showSingle = onlyOneChild && !onlyOneChild.children
@ -20,10 +20,7 @@
const {icon, title} = onlyOneChild.meta const {icon, title} = onlyOneChild.meta
return ( return (
<el-menu-item <el-menu-item index={onlyOneChild.fullPath}>
index={onlyOneChild.fullPath}
class={{'submenu-title-noDropdown': !isNest, 'nest-menu': isNest}}
>
<SidebarItemContent icon={icon} title={title}/> <SidebarItemContent icon={icon} title={title}/>
</el-menu-item> </el-menu-item>
) )
@ -31,8 +28,7 @@
else { else {
const {icon, title} = item.meta const {icon, title} = item.meta
const children = item.children.map(child => renderNode(h, { let children = item.children.map(child => renderNode(h, {
isNest: true,
item: child, item: child,
showParent, showParent,
collapse collapse
@ -42,16 +38,17 @@
if (collapse) { if (collapse) {
// //
if (showParent) { if (showParent) {
children.unshift( children = [
<div class="popover-menu__title el-menu-item"> <div class="popover-menu__title el-menu-item">
<SidebarItemContent icon={icon} title={title}/> <SidebarItemContent icon={icon} title={title}/>
</div> </div>,
) <div class="el-menu el-menu--inline">{children}</div>
]
} }
} }
return ( return (
<el-submenu class={{'nest-menu': isNest}} index={item.fullPath} popper-append-to-body> <el-submenu index={item.fullPath} popper-append-to-body>
<SidebarItemContent slot="title" icon={icon} title={title}/> <SidebarItemContent slot="title" icon={icon} title={title}/>
{children} {children}
</el-submenu> </el-submenu>
@ -64,7 +61,6 @@
props: { props: {
item: Object, item: Object,
isNest: Boolean,
showParent: Boolean, showParent: Boolean,
collapse: Boolean collapse: Boolean
}, },

@ -3,7 +3,6 @@
import Logo from './components/Logo' import Logo from './components/Logo'
import SidebarItem from './components/SidebarItem' import SidebarItem from './components/SidebarItem'
import {isExternal} from "@/utils/validate" import {isExternal} from "@/utils/validate"
import variables from '@/assets/styles/variables.scss'
export default { export default {
name: 'sidebar', name: 'sidebar',
@ -126,9 +125,6 @@
const menu = ( const menu = (
<el-menu <el-menu
ref="menu" ref="menu"
text-color={variables['menu-text-color']}
active-text-color={variables['menu-active-text-color']}
background-color={variables['menu-background']}
collapse={this.collapse} collapse={this.collapse}
collapse-transition={false} collapse-transition={false}
default-active={this.activeMenu} default-active={this.activeMenu}

@ -6,7 +6,7 @@ $iconSize: 17px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
width: $side-bar-width; width: $side-bar-width;
background-color: $menu-background; background-color: $--menu-background-color;
font-size: 0; font-size: 0;
flex-shrink: 0; flex-shrink: 0;
height: 100vh; height: 100vh;
@ -83,28 +83,6 @@ $iconSize: 17px;
right: 0; right: 0;
} }
} }
//子级菜单激活时父级同样高亮
.is-active > .el-submenu__title {
color: $--color-primary !important;
}
// menu hover
.submenu-title-noDropdown,
.el-submenu__title {
&:hover {
background-color: $menu-hover !important;
}
}
.nest-menu > .el-submenu__title,
.el-submenu .el-menu-item {
background-color: $sub-menu-background !important;
&:hover {
background-color: $sub-menu-hover !important;
}
}
} }
.el-menu { .el-menu {
@ -118,31 +96,46 @@ $iconSize: 17px;
height: $iconSize; height: $iconSize;
} }
a { //菜单hover
display: inline-block; .el-menu-item:hover,
width: 100%; .el-submenu__title:hover {
overflow: hidden; color: $--menu-item-hover-color;
} }
&.el-menu--popup { //子级菜单激活时父级同样高亮
max-height: 88vh; .el-menu-item.is-active,
margin-bottom: 0.5vh; .is-active > .el-submenu__title {
overflow-y: auto; color: $--color-primary !important;
overflow-y: overlay; }
//子级菜单的背景颜色
&.el-menu--inline,
.el-submenu .el-submenu > .el-submenu__title {
background-color: $sub-menu-background;
} }
//子级菜单内阴影
&.el-menu--inline {
box-shadow: inset 0 2px 8px rgba(0, 0, 0, .45)
}
//箭头图标与字体同色
.el-submenu__title i { .el-submenu__title i {
color: inherit; color: inherit;
} }
.popover-menu__title { //折叠时的弹出菜单
cursor: auto; &.el-menu--popup {
text-align: center; max-height: 88vh;
color: $menu-text-color; margin-bottom: 0.5vh;
border-bottom: 1px solid $sub-menu-background; overflow-y: overlay;
&.el-menu-item:hover { .popover-menu__title {
background-color: $menu-background; cursor: auto;
color: $--menu-item-hover-color;
text-align: center;
border-bottom: 1px solid $sub-menu-background;
} }
} }
} }

Loading…
Cancel
Save