index.vue 6.03 KB
Newer Older
葛齐林's avatar
葛齐林 committed
1 2 3 4 5
<template>
  <div v-if="true" class="d2-theme-header-menu" ref="page" :class="{'is-scrollable': isScroll}" flex="cross:center">
  <div v-if="true" class="d2-theme-header-menu" ref="page"  flex="cross:center">
    <div  class="d2-theme-header-menu__content m-theme-header-menu__content" ref="content" flex-box="1"  >
      <div  class="d2-theme-header-menu__scroll" ref="scroll" flex-box="0" :style="'transform: translateX(' + currentTranslateX + 'px);'">
co_dengxiongwen's avatar
co_dengxiongwen committed
6
        <el-menu mode="horizontal" :default-active="active" @select="handleMenuSelect" active-text-color=''>
葛齐林's avatar
葛齐林 committed
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
          <template v-for="(menu, menuIndex) in header">
            <d2-layout-header-aside-menu-item class="menu-item" :menu="menu" :key="menuIndex"/>
            <!-- <d2-layout-header-aside-menu-sub v-else :menu="menu" :key="menuIndex"/> -->
          </template>
        </el-menu>
      </div>
    </div>
    <div v-if="isScroll" class="d2-theme-header-menu__prev" style="height: 100%;" flex-box="0" @click="scroll('right')" flex="main:center cross:center">
      <i class="el-icon-arrow-left"></i>
    </div>
    <div v-if="isScroll" class="d2-theme-header-menu__next" style="height: 100%;" flex-box="0" @click="scroll('left')" flex="cross:center">
      <i class="el-icon-arrow-right"></i>
    </div>
  </div>
  </div>
</template>

<script>
import { throttle } from 'lodash'
import { mapState } from 'vuex'
import menuMixin from '../mixin/menu'
import d2LayoutMainMenuItem from '../components/menu-item/index.vue'
import d2LayoutMainMenuSub from '../components/menu-sub/index.vue'
export default {
  name: 'd2-layout-header-aside-menu-header',
  mixins: [
    menuMixin
  ],
  components: {
    'd2-layout-header-aside-menu-item': d2LayoutMainMenuItem,
    'd2-layout-header-aside-menu-sub': d2LayoutMainMenuSub
  },
  computed: {
    ...mapState('d2admin/menu', [
      'header'
    ])
  },
  data () {
    return {
      active: '',
      isScroll: false,
      scrollWidth: 0, //所有宽度
      contentWidth: 0, //可视宽度
      currentTranslateX: 0, //移动宽度
      throttledCheckScroll: null,
      menuWidth: 0, //(每个)菜单栏的宽度
      menuLength: 0 //菜单个数
    }
  },
  watch: {
    '$route.matched': {
      handler (val) {
        this.active = '/' + val[val.length - 1].path.split('/')[1]
      },
      immediate: true
    }
  },
  created () {
    this.$nextTick(() => {
      let arr = document.getElementsByClassName('el-menu-item menu-item')
      this.menuLength = arr.length
      this.menuWidth = arr[0].offsetWidth
    })
  },
  methods: {
    handleMenuSelect(index) {
      this.header.forEach(res => {
        if (res.path === index) {
          if (res.list && res.list.length) {
            if (res.list[0].path) {
              this.$router.push({
                path: res.list[0].path
              })
            } else {
              this.$router.push({
                path: index
              })
            }
          }
        }
      })
    },
    scroll (direction) {
      if (direction === 'left') {
        // 向右滚动
        //this.currentTranslateX += this.menuWidth * 2
        this.currentTranslateX -= this.menuWidth * 2
        if (this.currentTranslateX < 0) {
          this.currentTranslateX = 0
        }
      } else {
        // 向左滚动
        this.currentTranslateX += this.menuWidth * 2
        if (this.currentTranslateX > this.scrollWidth - this.contentWidth) {
            let width = Math.ceil((this.scrollWidth - this.contentWidth) / this.menuWidth)
            this.currentTranslateX = width * this.menuWidth
        }
      }
    },
    checkScroll () {
      let contentWidth = this.$refs.content.clientWidth
      let scrollWidth = this.$refs.scroll.clientWidth
      if (this.isScroll) {
        // 页面依旧允许滚动的情况,需要更新width
        if (this.contentWidth - this.scrollWidth === this.currentTranslateX) {
          // currentTranslateX 也需要相应变化【在右端到头的情况时】
          this.currentTranslateX = contentWidth - scrollWidth
          // 快速的滑动依旧存在判断和计算时对应的contentWidth变成正数,所以需要限制一下
          if (this.currentTranslateX > 0) {
            this.currentTranslateX = 0
          }
        }
        // 更新元素数据
        this.contentWidth = contentWidth
        this.scrollWidth = scrollWidth
        // 判断何时滚动消失: 当scroll > content
        if (contentWidth > scrollWidth) {
          this.isScroll = false
        }
      }
      // 判断何时滚动出现: 当scroll < content
      if (!this.isScroll && contentWidth < scrollWidth) {
        this.isScroll = true
        // 注意,当isScroll变为true,对应的元素盒子大小会发生变化
        this.$nextTick(() => {
          contentWidth = this.$refs.content.clientWidth
          scrollWidth = this.$refs.scroll.clientWidth
          this.contentWidth = contentWidth
          this.scrollWidth = scrollWidth
          this.currentTranslateX = 0
        })
      }
    }
  },
  mounted () {
    // 初始化判断
    // 默认判断父元素和子元素的大小,以确定初始情况是否显示滚动
    this.checkScroll()
    // 全局窗口变化监听,判断父元素和子元素的大小,从而控制isScroll的开关
    this.throttledCheckScroll = throttle(this.checkScroll, 300)
    window.addEventListener('resize', this.throttledCheckScroll)
  },
  beforeDestroy () {
    // 取消监听
    window.removeEventListener('resize', this.throttledCheckScroll)
  }
}
</script>
<style lang="scss" scoped>
.menu-item{
  display:flex !important;
  flex-direction: column;
  height: 90px;
  justify-content: flex-end;
  align-items: center;
}
</style>
<style>

.el-menu--horizontal>.el-menu-item {
    line-height: 52px;
    font-size:14px;
    font-family:Microsoft YaHei;
    font-weight:400;
}
.m-theme-header-menu__content{
  display:flex;
  justify-content:flex-end;
  margin-right:45px;
}
</style>