赞
踩
目录
1.复制一份src/layout/componets/Sidebar所有文件至同级目录,改名为Headbar,并在src/layout/components/index.js中声明Headbar
声明Headbar
2.修改Headbar/index.vue文件内容,主要删除了logo和更改了el-menu的mode属性为horizontal,并将name更改为Headbar;
- <template>
- <el-scrollbar wrap-class="scrollbar-wrapper">
- <el-menu
- :default-active="activeMenu"
- :background-color="variables.menuBg"
- :text-color="variables.menuText"
- :active-text-color="variables.menuActiveText"
- mode="horizontal">
-
- <sidebar-item
- v-for="route in permission_routes"
- :key="route.path"
- :item="route"
- :base-path="route.path"/>
- </el-menu>
- </el-scrollbar>
-
- </template>
-
- <script>
- import {mapGetters} from 'vuex'
- import SidebarItem from './SidebarItem'
- import variables from '@/styles/variables.scss'
-
- export default {
- name: 'Headbar',
- components: {SidebarItem},
- computed: {
- ...mapGetters([
- 'permission_routes',
- 'sidebar'
- ]),
- activeMenu() {
- const route = this.$route
- const {meta, path} = route
- // if set path, the sidebar will highlight the path you set
- if (meta.activeMenu) {
- return meta.activeMenu
- }
- return path
- },
- showLogo() {
- return this.$store.state.settings.sidebarLogo
- },
- variables() {
- return variables
- },
- isCollapse() {
- return !this.sidebar.opened
- }
- }
- }
- </script>
3.修改Headbar/SidebarItem.vue文件内容,主要配置stype、删除icon、增加固定宽度;
- <template>
- <!-- style设置为inline-block,避免垂直布局的标题-->
- <div v-if="!item.hidden" style="display:inline-block;">
- <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)">
- <item :title="generateTitle(onlyOneChild.meta.title)"/>
- </el-menu-item>
- </app-link>
- </template>
-
- <el-submenu v-else ref="subMenu" :index="resolvePath(item.path)" >
- <template slot="title">
- <item v-if="item.meta" :title="generateTitle(item.meta.title)"/>
- <!-- 增加固定宽度防止箭头被遮挡-->
- <div style="display: inline-block; width:20px;"></div>
- </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 {generateTitle} from '@/utils/i18n'
- import {isExternal} from '@/utils/validate'
- import Item from './Item'
- import AppLink from './Link'
- import FixiOSBug from './FixiOSBug'
- import SidebarItem from "./SidebarItem";
-
- export default {
- name: 'SidebarItem',
- components: {Item, AppLink, SidebarItem},
- 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: refactor with render function
- this.onlyOneChild = null
- return {}
- },
- methods: {
- hasOneShowingChild(children = [], parent) {
- const showingChildren = children.filter(item => {
- if (item.hidden) {
- return false
- } else {
- // Temp set(will be used if only has one showing child)
- this.onlyOneChild = item
- return true
- }
- })
-
- // When there is only one child router, the child router is displayed by default
- if (showingChildren.length === 1) {
- return true
- }
-
- // Show parent if there are no child router to display
- 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)
- },
-
- generateTitle
- }
- }
- </script>
1.在src/settings.js中增加menuInLeft
2.在右侧边栏中增加切换按钮,src/layout/components/Settings/index.vue
- <template>
- <div class="drawer-container">
- <div>
- <!--原有标签保持不变,此处省略-->
-
- <!--增加切换按钮-->
- <div class="drawer-item">
- <span>切换菜单位置</span>
- <el-switch v-model="menuInLeft" class="drawer-switch" />
- </div>
-
- </div>
- </div>
- </template>
-
- <script>
- import ThemePicker from '@/components/ThemePicker'
-
- export default {
- components: { ThemePicker },
- data() {
- return {}
- },
- computed: {
- // ===原有参数保持不变,此处省略====
-
- // 增加绑定的menuInLeft值
- menuInLeft: {
- get() {
- return this.$store.state.settings.menuInLeft
- },
- set(val) {
- this.$store.dispatch('settings/changeSetting', {
- key: 'menuInLeft',
- value: val
- })
- }
- },
- },
- methods: {
- themeChange(val) {
- this.$store.dispatch('settings/changeSetting', {
- key: 'theme',
- value: val
- })
- }
- }
- }
- </script>
-
- <style lang="scss" scoped>
- /*原有样式保持不变,此处省略*/
- </style>
3.引入menuInLeft,src/store/modules/settings.js
1.配置index.vue(src/layout/inex.vue)
- <template>
- <div :class="classObj" class="app-wrapper">
-
- <div v-if="device==='mobile'&&sidebar.opened" class="drawer-bg" @click="handleClickOutside"/>
-
- <!--当 menuInLeft===true,左菜单栏显示,顶部隐藏-->
- <sidebar class="sidebar-container" v-if="menuInLeft"/>
-
- <!--当左菜单栏显示时,需配置main-container 样式,改样式位置在src/styles/sidebar.scss文件中-->
- <div :class="{hasTagsView:needTagsView,'main-container':menuInLeft}">
- <div :class="{'fixed-header':fixedHeader}">
-
- <navbar/>
-
- <!--当 menuInLeft===false,左菜单栏隐藏,顶部显示-->
- <headbar v-if="!menuInLeft"/>
-
- <tags-view v-if="needTagsView"/>
- </div>
-
- <app-main/>
-
- <right-panel v-if="showSettings">
- <settings/>
- </right-panel>
- </div>
- </div>
-
- </template>
-
- <script>
- import RightPanel from '@/components/RightPanel'
- //引入Sidebar
- import {AppMain, Navbar, Settings, Headbar, Sidebar, TagsView} from './components'
- import ResizeMixin from './mixin/ResizeHandler'
- import {mapState} from 'vuex'
-
- export default {
- name: 'Layout',
- components: {
- AppMain,
- Navbar,
- RightPanel,
- Settings,
- Sidebar,//引入Sidebar
- Headbar,
- TagsView
- },
- mixins: [ResizeMixin],
- computed: {
- ...mapState({
- sidebar: state => state.app.sidebar,
- device: state => state.app.device,
- showSettings: state => state.settings.showSettings,
- needTagsView: state => state.settings.tagsView,
- fixedHeader: state => state.settings.fixedHeader,
- //获取menuInLeft值
- menuInLeft: state => state.settings.menuInLeft
- }),
- classObj() {
- return {
- hideSidebar: !this.sidebar.opened,
- openSidebar: this.sidebar.opened,
- withoutAnimation: this.sidebar.withoutAnimation,
- mobile: this.device === 'mobile'
- }
- }
- },
- methods: {
- handleClickOutside() {
- this.$store.dispatch('app/closeSideBar', {withoutAnimation: false})
- }
- }
- }
- </script>
2、配置Navbar.vue(src/layout/components/Navbar.vue)
- <template>
- <div class="navbar">
- <!--注释 侧边栏展开关闭按钮-->
- <hamburger v-if="menuInLeft"
- id="hamburger-container"
- :is-active="sidebar.opened"
- class="hamburger-container"
- @toggleClick="toggleSideBar"/>
-
- <breadcrumb id="breadcrumb-container" class="breadcrumb-container"/>
-
- <div class="right-menu">
-
- <template v-if="device!=='mobile'">
- <search id="header-search" class="right-menu-item"/>
-
- <error-log class="errLog-container right-menu-item hover-effect"/>
-
- <screenfull id="screenfull" class="right-menu-item hover-effect"/>
-
- <el-tooltip :content="$t('navbar.size')" effect="dark" placement="bottom">
- <size-select id="size-select" class="right-menu-item hover-effect"/>
- </el-tooltip>
-
- <lang-select class="right-menu-item hover-effect"/>
-
- </template>
-
- <el-dropdown class="avatar-container right-menu-item hover-effect" trigger="click">
- <div class="avatar-wrapper">
- <img :src="avatar+'?imageView2/1/w/80/h/80'" class="user-avatar">
- <i class="el-icon-caret-bottom"/>
- </div>
- <el-dropdown-menu slot="dropdown">
- <router-link to="/profile/index">
- <el-dropdown-item>
- {{ $t('navbar.profile') }}
- </el-dropdown-item>
- </router-link>
- <router-link to="/">
- <el-dropdown-item>
- {{ $t('navbar.dashboard') }}
- </el-dropdown-item>
- </router-link>
- <a target="_blank" href="https://github.com/PanJiaChen/vue-element-admin/">
- <el-dropdown-item>
- {{ $t('navbar.github') }}
- </el-dropdown-item>
- </a>
- <a target="_blank" href="https://panjiachen.github.io/vue-element-admin-site/#/">
- <el-dropdown-item>Docs</el-dropdown-item>
- </a>
- <el-dropdown-item divided @click.native="logout">
- <span style="display:block;">{{ $t('navbar.logOut') }}</span>
- </el-dropdown-item>
- </el-dropdown-menu>
- </el-dropdown>
- </div>
-
- </div>
- </template>
-
- <script>
- import {mapGetters, mapState} from 'vuex'
- import Breadcrumb from '@/components/Breadcrumb'
- import Hamburger from '@/components/Hamburger'
- import ErrorLog from '@/components/ErrorLog'
- import Screenfull from '@/components/Screenfull'
- import SizeSelect from '@/components/SizeSelect'
- import LangSelect from '@/components/LangSelect'
- import Search from '@/components/HeaderSearch'
-
- export default {
- components: {
- Breadcrumb,
- Hamburger,
- ErrorLog,
- Screenfull,
- SizeSelect,
- LangSelect,
- Search,
- },
- computed: {
- ...mapGetters([
- 'sidebar',
- 'avatar',
- 'device'
- ]),
- ...mapState({
- menuInLeft: state => state.settings.menuInLeft
- }),
- },
- methods: {
- toggleSideBar() {
- this.$store.dispatch('app/toggleSideBar')
- },
- async logout() {
- await this.$store.dispatch('user/logout')
- this.$router.push(`/login?redirect=${this.$route.fullPath}`)
- }
- }
- }
- </script>
-
- <style lang="scss" scoped>
- .navbar {
- height: 50px;
- overflow: hidden;
- position: relative;
- background: #fff;
- box-shadow: 0 1px 4px rgba(0, 21, 41, .08);
-
- .hamburger-container {
- line-height: 46px;
- height: 100%;
- float: left;
- cursor: pointer;
- transition: background .3s;
- -webkit-tap-highlight-color: transparent;
-
- &:hover {
- background: rgba(0, 0, 0, .025)
- }
- }
-
- .breadcrumb-container {
- float: left;
- }
-
- .errLog-container {
- display: inline-block;
- vertical-align: top;
- }
-
- .right-menu {
- float: right;
- height: 100%;
- line-height: 50px;
-
- &:focus {
- outline: none;
- }
-
- .right-menu-item {
- display: inline-block;
- padding: 0 8px;
- height: 100%;
- font-size: 18px;
- color: #5a5e66;
- vertical-align: text-bottom;
-
- &.hover-effect {
- cursor: pointer;
- transition: background .3s;
-
- &:hover {
- background: rgba(0, 0, 0, .025)
- }
- }
- }
-
- .avatar-container {
- margin-right: 30px;
-
- .avatar-wrapper {
- margin-top: 5px;
- position: relative;
-
- .user-avatar {
- cursor: pointer;
- width: 40px;
- height: 40px;
- border-radius: 10px;
- }
-
- .el-icon-caret-bottom {
- cursor: pointer;
- position: absolute;
- right: -20px;
- top: 25px;
- font-size: 12px;
- }
- }
- }
- }
- }
- </style>
-----------------------------------------------------------分割线-------------------------------------------------------------
说明:
上面文章中用的是vue-element-amdin的,i18n版本(增加了多语言功能),generateTitle方法是原项目默认的,在代码的import位置进行了引用。
评论中的百度云源代码使用的是项目的master版本,里面没有generateTitle。
-----------------------------------------------------------分割线-------------------------------------------------------------
直接在layout/components/Navbar.vue中引入 headbar,并加入headbar标签即可。效果如下:
由于顶部位置有限,在菜单过多时,会存在放不下的情况。代码中为了将位置空出来,我把breadrumb标签进行了隐藏,不过还是没有放下…………
最好的解决方式是让顶部菜单能够左右滑动,目前还没有去调试加上,先进行记录一下, 后面调试出来了再加。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。