路由主布局代码优化

master
toesbieya 6 years ago
parent dd6f87ed04
commit 163e803939
  1. 4
      vue/src/layout/component/Navbar/component/Bell.vue
  2. 4
      vue/src/layout/component/Navbar/component/Hamburger.vue
  3. 49
      vue/src/layout/component/Navbar/index.vue
  4. 93
      vue/src/layout/component/Sidebar/component/SidebarItem.vue
  5. 73
      vue/src/layout/component/Sidebar/index.vue
  6. 4
      vue/src/layout/component/TagsView/ScrollPane.vue
  7. 14
      vue/src/layout/component/TagsView/index.vue
  8. 0
      vue/src/layout/component/TagsView/mixin/shortcut.js

@ -1,6 +1,6 @@
<template> <template>
<el-badge :hidden="hidden" class="bell-badge" is-dot @click.native="jump"> <el-badge :hidden="hidden" class="bell-badge" is-dot title="消息提醒" @click.native="jump">
<i class="el-icon-bell navbar-icon" title="消息提醒"/> <i class="el-icon-bell navbar-icon"/>
</el-badge> </el-badge>
</template> </template>

@ -8,9 +8,9 @@ export default {
render(h, context) { render(h, context) {
const {active} = context.props const {active} = context.props
const className = {'navbar-icon': true, 'el-icon-s-unfold': true, 'hamburger': true, 'is-active': active} const className = `navbar-icon el-icon-s-unfold hamburger ${active ? 'is-active' : ''}`
return ( return (
<div {...context.data}> <div {...context.data} title={`${active ? '折叠' : '展开'}侧边栏`}>
<i class={className}/> <i class={className}/>
</div> </div>
) )

@ -3,37 +3,38 @@
<div> <div>
<hamburger class="navbar-item" :active="!sidebarCollapse" @click="sidebarCtrl"/> <hamburger class="navbar-item" :active="!sidebarCollapse" @click="sidebarCtrl"/>
<div class="navbar-item" @click="refresh">
<i class="el-icon-refresh-right navbar-icon" title="刷新"/>
</div>
<breadcrumb v-if="showBreadcrumb"/> <breadcrumb v-if="showBreadcrumb"/>
</div> </div>
<div> <div>
<bell class="navbar-item"/> <bell class="navbar-item"/>
<div class="setting-btn navbar-item hidden-xs" @click="settingDrawer=true"> <div class="navbar-item" title="刷新" @click="refresh">
<i class="el-icon-s-operation navbar-icon" title="个性设置"/> <i class="el-icon-refresh-right navbar-icon"/>
</div>
<div class="setting-btn navbar-item hidden-xs" title="个性设置" @click="settingDrawer = true">
<i class="el-icon-s-operation navbar-icon"/>
</div> </div>
<el-dropdown <el-dropdown
class="navbar-item" class="navbar-item"
trigger="click" trigger="click"
@visible-change="$emit('menu-show',$event)" @command="command"
@visible-change="e => $emit('menu-show',e)"
> >
<div class="avatar-wrapper"> <div class="avatar-wrapper">
<el-avatar :size="30" :src="avatar" icon="el-icon-user-solid"/> <el-avatar :size="30" :src="avatar" icon="el-icon-user-solid"/>
<span class="hidden-xs">{{ name }}</span> <span class="hidden-xs">{{ name }}</span>
</div> </div>
<el-dropdown-menu class="user-dropdown" slot="dropdown"> <el-dropdown-menu class="user-dropdown" slot="dropdown">
<router-link to="/user"> <el-dropdown-item icon="el-icon-user" command="user">
<el-dropdown-item icon="el-icon-user">个人中心</el-dropdown-item> 个人中心
</router-link> </el-dropdown-item>
<el-dropdown-item class="hidden-xs" icon="el-icon-guide" @click.native="()=>$guide(0,guideSteps)"> <el-dropdown-item class="hidden-xs" icon="el-icon-guide" command="guide">
新手指引 新手指引
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item divided icon="el-icon-switch-button" @click.native="logout"> <el-dropdown-item divided icon="el-icon-switch-button" command="logout">
退出登录 退出登录
</el-dropdown-item> </el-dropdown-item>
</el-dropdown-menu> </el-dropdown-menu>
@ -61,11 +62,7 @@ export default {
components: {Hamburger, Breadcrumb, Bell, SettingDrawer}, components: {Hamburger, Breadcrumb, Bell, SettingDrawer},
data() { data: () => ({settingDrawer: false}),
return {
settingDrawer: false
}
},
computed: { computed: {
...mapState('user', ['avatar', 'name', 'prepareLogout']), ...mapState('user', ['avatar', 'name', 'prepareLogout']),
@ -77,15 +74,23 @@ export default {
sidebarCtrl() { sidebarCtrl() {
this.$store.commit('setting/sidebarCollapse', !this.sidebarCollapse) this.$store.commit('setting/sidebarCollapse', !this.sidebarCollapse)
}, },
refresh() { refresh() {
this.$router.replace({path: `/redirect${this.$route.fullPath}`}) this.$router.replace({path: `/redirect${this.$route.fullPath}`})
}, },
logout() { command(command) {
if (this.prepareLogout) return switch (command) {
elConfirm('确认退出?') case 'user':
.then(() => this.$store.dispatch('user/logout')) this.$router.push('/user')
break
case 'guide':
this.$guide(0, this.guideSteps)
break
case 'logout':
if (this.prepareLogout) return
elConfirm('确认退出?').then(() => this.$store.dispatch('user/logout'))
break
}
} }
} }
} }

@ -1,72 +1,83 @@
<script type="text/jsx"> <script type="text/jsx">
import SidebarItemContent from './SidebarItemContent' import SidebarItemContent from './SidebarItemContent'
function getOnlyChild(item) { //
const {children = [], meta: {alwaysShow} = {}} = item function getOnlyChild(menu) {
const {children = [], meta: {alwaysShow} = {}} = menu
if (children.length === 1) return alwaysShow ? null : children[0] if (!children.length) return {...menu, children: undefined}
if (!children.length) return {...item, path: undefined, children: undefined} if (children.length === 1) return alwaysShow ? null : getOnlyChild(children[0])
return null return null
} }
function renderNode(h, {item, showParent, collapse}) { function renderSingleMenu(h, {index, icon, title}) {
let onlyOneChild = getOnlyChild(item) return (
<el-menu-item index={index}>
<SidebarItemContent icon={icon} title={title}/>
</el-menu-item>
)
}
function renderSubMenu(h, {index, icon, title, children}) {
return (
<el-submenu index={index} popper-append-to-body>
<SidebarItemContent slot="title" icon={icon} title={title}/>
{children}
</el-submenu>
)
}
function renderChildrenWithParentMenu(h, {icon, title, children}) {
return [
<div class="popover-menu__title el-menu-item">
<SidebarItemContent icon={icon} title={title}/>
</div>,
<div class="el-menu el-menu--inline">{children}</div>
]
}
function renderMenu(h, {menu, showParent, collapse}) {
const onlyOneChild = getOnlyChild(menu)
const showSingle = onlyOneChild && !onlyOneChild.children const showSingle = onlyOneChild && !onlyOneChild.children
if (showSingle) { if (showSingle) {
const {icon, title} = onlyOneChild.meta const {icon, title} = onlyOneChild.meta
return renderSingleMenu(h, {index: onlyOneChild.fullPath, icon, title})
return (
<el-menu-item index={onlyOneChild.fullPath}>
<SidebarItemContent icon={icon} title={title}/>
</el-menu-item>
)
} }
else {
const {icon, title} = item.meta
let children = item.children.map(child => renderNode(h, {
item: child,
showParent,
collapse
}))
//mouseleavemouseleave
if (collapse) {
//
if (showParent) {
children = [
<div class="popover-menu__title el-menu-item">
<SidebarItemContent icon={icon} title={title}/>
</div>,
<div class="el-menu el-menu--inline">{children}</div>
]
}
}
return ( const {icon, title} = menu.meta
<el-submenu index={item.fullPath} popper-append-to-body>
<SidebarItemContent slot="title" icon={icon} title={title}/> let children = menu.children.map(child => renderMenu(h, {
{children} menu: child,
</el-submenu> showParent,
) collapse
}))
//<el-scrollbar>mouseleavemouseleave
if (collapse) {
//
if (showParent) {
children = renderChildrenWithParentMenu(h, {icon, title, children})
}
} }
return renderSubMenu(h, {index: menu.fullPath, icon, title, children})
} }
export default { export default {
functional: true, functional: true,
props: { props: {
item: Object, menu: Object,
showParent: Boolean, showParent: Boolean,
collapse: Boolean collapse: Boolean
}, },
render(h, context) { render(h, context) {
return renderNode(h, context.props) return renderMenu(h, context.props)
} }
} }
</script> </script>

@ -9,11 +9,7 @@ export default {
components: {SidebarItem, Logo}, components: {SidebarItem, Logo},
data() { data: () => ({mouseOutside: true, activeMenu: ''}),
return {
mouseOutside: true
}
},
computed: { computed: {
...mapState('app', ['device']), ...mapState('app', ['device']),
@ -22,20 +18,14 @@ export default {
...mapState('setting', ['showLogo', 'sidebarCollapse', 'sidebarUniqueOpen', 'sidebarShowParent', 'sidebarAutoHidden']), ...mapState('setting', ['showLogo', 'sidebarCollapse', 'sidebarUniqueOpen', 'sidebarShowParent', 'sidebarAutoHidden']),
activeMenu() {
const route = this.$route
const {meta, path} = route
if (path.startsWith('/redirect')) {
return path.replace('/redirect', '')
}
return meta.activeMenu || path
},
//pc //pc
collapse() { collapse() {
return this.sidebarCollapse && this.device === 'pc' return this.sidebarCollapse && this.device === 'pc'
}, },
//
//
//
hideSidebar() { hideSidebar() {
return this.sidebarAutoHidden && this.mouseOutside return this.sidebarAutoHidden && this.mouseOutside
|| this.sidebarCollapse && this.device === 'mobile' || this.sidebarCollapse && this.device === 'mobile'
@ -53,19 +43,33 @@ export default {
watch: { watch: {
//elMenuinitOpenedMenu()select //elMenuinitOpenedMenu()select
'$route.path'(nv, ov) { '$route.path': {
//redirect immediate: true,
if (nv === `/redirect${ov}`) return handler(v) {
const menu = this.$refs.menu //redirect
if (!menu) return if (v.startsWith('/redirect')) return
const item = menu.items[this.activeMenu]
if (!item) menu.openedMenus = [] this.setActiveMenu()
else this.select(item.index, item.indexPath, item, false)
const menu = this.$refs.menu
if (!menu) return
const item = menu.items[this.activeMenu]
//
if (!item) return menu.openedMenus = []
this.select(item.index, item.indexPath, item, false)
}
}, },
hideSidebar(v) { //
if (v) document.addEventListener('mousemove', this.moveEvent) hideSidebar: {
else document.removeEventListener('mousemove', this.moveEvent) immediate: true,
handler(v) {
if (!this.sidebarAutoHidden) return
const key = `${v ? 'add' : 'remove'}EventListener`
document[key]('mousemove', this.moveEvent)
}
} }
}, },
@ -74,6 +78,13 @@ export default {
if (e.clientX <= 15) this.mouseOutside = false if (e.clientX <= 15) this.mouseOutside = false
}, },
//
setActiveMenu() {
const {meta, path} = this.$route
this.activeMenu = meta.activeMenu || path
},
//
select(index, indexPath, item, jump = true) { select(index, indexPath, item, jump = true) {
// //
if (this.sidebarUniqueOpen && indexPath.length === 1) { if (this.sidebarUniqueOpen && indexPath.length === 1) {
@ -100,14 +111,8 @@ export default {
} }
}, },
mounted() { beforeDestroy() {
if (this.sidebarAutoHidden) { document.removeEventListener('mousemove', this.moveEvent)
document.addEventListener('mousemove', this.moveEvent)
}
this.$once('hook:beforeDestroy', () => {
document.removeEventListener('mousemove', this.moveEvent)
})
}, },
render() { render() {
@ -126,7 +131,7 @@ export default {
key={menu.path} key={menu.path}
show-parent={this.sidebarShowParent} show-parent={this.sidebarShowParent}
collapse={this.sidebarCollapse} collapse={this.sidebarCollapse}
item={menu} menu={menu}
/> />
))} ))}
</el-menu> </el-menu>

@ -1,5 +1,5 @@
<template> <template>
<el-scrollbar ref="scrollContainer" native @wheel.native.prevent="handleScroll"> <el-scrollbar ref="scrollContainer" native noresize @wheel.native.prevent="handleScroll">
<slot/> <slot/>
</el-scrollbar> </el-scrollbar>
</template> </template>
@ -10,8 +10,6 @@ const tagAndTagSpacing = 4
export default { export default {
name: 'ScrollPane', name: 'ScrollPane',
data: () => ({rAF: null}),
methods: { methods: {
getWrapper() { getWrapper() {
return this.$refs.scrollContainer.$refs.wrap return this.$refs.scrollContainer.$refs.wrap

@ -8,8 +8,8 @@
:class="{'tags-view-item': true, active: isActive(tag)}" :class="{'tags-view-item': true, active: isActive(tag)}"
:to="{ path: tag.path, query: tag.query, fullPath: tag.fullPath }" :to="{ path: tag.path, query: tag.query, fullPath: tag.fullPath }"
tag="div" tag="div"
@contextmenu.prevent.native="e => openMenu(tag, e)" @contextmenu.prevent.stop.native="e => openMenu(tag, e)"
@dblclick.prevent.native="() => closeSelectedTag(tag)" @dblclick.prevent.stop.native="() => closeSelectedTag(tag)"
> >
{{ tag.title }} {{ tag.title }}
<i v-if="!isAffix(tag)" class="el-icon-close" @click.prevent.stop="() => closeSelectedTag(tag)"/> <i v-if="!isAffix(tag)" class="el-icon-close" @click.prevent.stop="() => closeSelectedTag(tag)"/>
@ -27,15 +27,15 @@
</nav> </nav>
</template> </template>
<script> <script type="text/jsx">
import ScrollPane from './ScrollPane' import shortcutMixin from './mixin/shortcut'
import decideRouterTransitionMixin from './mixin/decideRouterTransition'
import ContextMenu from "@/component/ContextMenu" import ContextMenu from "@/component/ContextMenu"
import ContextMenuItem from "@/component/ContextMenu/item" import ContextMenuItem from "@/component/ContextMenu/item"
import shortcuts from './mixin/shortcuts' import ScrollPane from './ScrollPane'
import decideRouterTransition from './mixin/decideRouterTransition'
export default { export default {
mixins: [shortcuts, decideRouterTransition], mixins: [shortcutMixin, decideRouterTransitionMixin],
components: {ContextMenu, ContextMenuItem, ScrollPane}, components: {ContextMenu, ContextMenuItem, ScrollPane},

Loading…
Cancel
Save