zoukankan      html  css  js  c++  java
  • vue-element-template实战(六)实现顶部一级菜单,左侧二级及二级以下菜单

    总思路:

    一、在layout里加了一个Topbar组件,地址为:src/layout/components/Topbar.vue

    Topbar.vue代码如下:

    <template>
      <div class="top-nav">
        <div class="log">一级导航</div>
        <el-menu
          :active-text-color="variables.menuActiveText"
          :default-active="activeMenu"
          mode="horizontal"
          @select="handleSelect"
        >
          <div v-for="item in routes" :key="item.path" class="nav-item">
            <app-link :to="resolvePath(item)">
              <el-menu-item
                v-if="!item.hidden"
                :index="item.path"
              >{{ item.meta ? item.meta.title : item.children[0].meta.title }}</el-menu-item>
            </app-link>
          </div>
        </el-menu>
    
        <div class="right-menu">
          <el-dropdown class="avatar-container" 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" class="user-dropdown">
              <router-link to="/">
                <el-dropdown-item>Home</el-dropdown-item>
              </router-link>
              <a href="https://github.com/PanJiaChen/vue-admin-template/" target="_blank">
                <el-dropdown-item>Github</el-dropdown-item>
              </a>
              <a href="https://panjiachen.github.io/vue-element-admin-site/#/" target="_blank">
                <el-dropdown-item>Docs</el-dropdown-item>
              </a>
              <el-dropdown-item divided @click.native="logout">
                <span style="display:block;">Log Out</span>
              </el-dropdown-item>
            </el-dropdown-menu>
          </el-dropdown>
        </div>
      </div>
    </template>
    
    <script>
    import { mapGetters } from 'vuex'
    import AppLink from './Sidebar/Link'
    import { constantRoutes } from '@/router'
    import variables from '@/styles/variables.scss'
    import { isExternal } from '@/utils/validate'
    
    export default {
      name: 'Topbar',
      components: {
        AppLink
      },
      data() {
        return {
          routes: constantRoutes
        }
      },
      computed: {
        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
          }
          // 如果是首页,首页高亮
          if (path === '/dashboard') {
            return '/'
          }
          // 如果不是首页,高亮一级菜单
          const activeMenu = '/' + path.split('/')[1]
          return activeMenu
        },
        variables() {
          return variables
        },
        sidebar() {
          return this.$store.state.app.sidebar
        },
        ...mapGetters(['avatar'])
      },
      mounted() {
        this.initCurrentRoutes()
      },
      methods: {
        // 通过当前路径找到二级菜单对应项,存到store,用来渲染左侧菜单
        initCurrentRoutes() {
          const { path } = this.$route
          let route = this.routes.find(
            item => item.path === '/' + path.split('/')[1]
          )
          // 如果找不到这个路由,说明是首页
          if (!route) {
            route = this.routes.find(item => item.path === '/')
          }
          this.$store.commit('permission/SET_CURRENT_ROUTES', route)
          this.setSidebarHide(route)
        },
        // 判断该路由是否只有一个子项或者没有子项,如果是,则在一级菜单添加跳转路由
        isOnlyOneChild(item) {
          if (item.children && item.children.length === 1) {
            return true
          }
          return false
        },
        resolvePath(item) {
          // 如果是个完成的url直接返回
          if (isExternal(item.path)) {
            return item.path
          }
          // 如果是首页,就返回重定向路由
          if (item.path === '/') {
            const path = item.redirect
            return path
          }
    
          // 如果有子项,默认跳转第一个子项路由
          let path = ''
          /**
           * item 路由子项
           * parent 路由父项
           */
          const getDefaultPath = (item, parent) => {
            // 如果path是个外部链接(不建议),直接返回链接,存在个问题:如果是外部链接点击跳转后当前页内容还是上一个路由内容
            if (isExternal(item.path)) {
              path = item.path
              return
            }
            // 第一次需要父项路由拼接,所以只是第一个传parent
            if (parent) {
              path += (parent.path + '/' + item.path)
            } else {
              path += ('/' + item.path)
            }
            // 如果还有子项,继续递归
            if (item.children) {
              getDefaultPath(item.children[0])
            }
          }
    
          if (item.children) {
            getDefaultPath(item.children[0], item)
            return path
          }
    
          return item.path
        },
        handleSelect(key, keyPath) {
          // 把选中路由的子路由保存store
          const route = this.routes.find(item => item.path === key)
          this.$store.commit('permission/SET_CURRENT_ROUTES', route)
          this.setSidebarHide(route)
        },
        // 设置侧边栏的显示和隐藏
        setSidebarHide(route) {
          if (!route.children || route.children.length === 1) {
            this.$store.dispatch('app/toggleSideBarHide', true)
          } else {
            this.$store.dispatch('app/toggleSideBarHide', false)
          }
        },
        async logout() {
          await this.$store.dispatch('user/logout')
          this.$router.push(`/login?redirect=${this.$route.fullPath}`)
        }
      }
    }
    </script>
    View Code

    二、修改src/layout/index.vue

    <template>
      <div :class="classObj" class="app-wrapper">
        <topbar />  <!-- 此处增加topbar-->
        <div v-if="device==='mobile'&&sidebar.opened" class="drawer-bg" @click="handleClickOutside" />
        <!-- 侧边栏展示的li列表-->
        <sidebar class="sidebar-container" />
        <div class="main-container">
          <div :class="{'fixed-header':fixedHeader}">
            <!-- 导航 -->
            <navbar />
          </div>
          <tags-view />  <!-- 此处增加tag-->
          <!-- 主体部分 -->
          <app-main />
        </div>
      </div>
    </template>
    import { Navbar, Sidebar, AppMain, TagsView ,Topbar } from './components'
      components: {
        Navbar,
        Sidebar,
        AppMain,
        TagsView,
        Topbar
      },
    .app-wrapper {
        @include clearfix;
        position: relative;
        //height: 100%;
        height: $contentHeight;
         100%;
        &.mobile.openSidebar{
          position: fixed;
          top: 0;
        }
      }

    三、修改src/styles/variables.scss

    $sideBarWidth: 210px;
    $topBarHeight: 56px;
    $contentHeight: calc(100vh - 56px);

    四、新增src/store/modules/permission.js

    import { constantRoutes } from '@/router'
    
    const state = {
      routes: [],
      addRoutes: [],
      currentRoutes: {}
    }
    
    const mutations = {
      SET_ROUTES: (state, routes) => {
        state.addRoutes = routes
        state.routes = constantRoutes.concat(routes)
      },
      SET_CURRENT_ROUTES: (state, routes) => {
        state.currentRoutes = routes
      }
    }
    
    export default {
      namespaced: true,
      state,
      mutations
    }

    五、修改src/store/index.js

    import Vue from 'vue'
    import Vuex from 'vuex'
    import getters from './getters'
    import app from './modules/app'
    import settings from './modules/settings'
    import user from './modules/user'
    import tagsView from './modules/tagsView'
    import permission from './modules/permission'  //新增
    
    Vue.use(Vuex)
    
    const store = new Vuex.Store({
      modules: {
        app,
        settings,
        tagsView,
        user,
        permission   //新增
      },
      getters
    })
    
    export default store

    六、

    src/store/modules/permission.js
  • 相关阅读:
    UVA11825 Hackers' Crackdown
    UVA 11346 Probability
    Codeforces 12 D Ball
    bzoj 4766: 文艺计算姬
    Codeforces 757 F Team Rocket Rises Again
    [HAOI2011] problem C
    Atcoder 3857 Median Sum
    bzoj4399 魔法少女LJJ
    bzoj2638 黑白染色
    bzoj4197 [Noi2015]寿司晚宴
  • 原文地址:https://www.cnblogs.com/windok/p/13683187.html
Copyright © 2011-2022 走看看