[饿了么 导航菜单组件] VUE全局导航菜单组件

1,600 阅读2分钟

效果 如图:

1.接下来, 我们会围绕组件的 几个点展开讨论:

如何把组件引入全局使用 如何控制菜单在一级页面显示 菜单如何获取当前的路由并且高亮

技术点讲解:

  1. 如何把组件引入全局使用 如果你用的是nuxt.js框架,只需在 layouts/default.vue 引入就可以了,这样保证了组件在所有页面之前显示.

  2. 如何控制菜单在一级页面显示 我们引用菜单组件的时候,定义一个显示页面名称的数组,与当前路由做匹配来控制菜单组件的显示

    // html
      Menu(v-show="isShowMenu")
    // javascript
      data () {
        return {
          // 把需要显示menuBar的路由name填入
          showMenuList: ['A', 'demo', 'B', 'C', 'D', 'E']
        }
      },
      computed: {
        /**
         * 是否显示menuBar
         * @return {Boolean}
         */
        isShowMenu () {
          return this.showMenuList.indexOf(this.$route.name) >= 0 && !this.dontShowMenu
        },
        /**
         * 不显示菜单
         * @return {Boolean}
         */
        dontShowMenu () {
          return this.$store.state.common.dontShowMenu
        }
      },
    
    1. 菜单如何获取当前的路由并且高亮 我们通过获取当前路由与当前页面名匹配,利用vue的:class绑定样式变量实现

        computed: {
          /**
           * 渲染数组
           * @return {String}
           */
          menuList () {
            // 计算样式
            let common = (item) => {
              return [this.$route.name === item ? 'current' : '', `.iconfont.icon-${item}`]
            }
            // 菜单组件基础数据
            let list = [
              { key: 'A',
                style: common('A') },
              { key: 'B',
                style: common('B') },
              { key: 'C',
                style: common('C') },
              { key: 'D',
                style: common('D') }
            ]
            return list
          }
        },
      

全部代码

组件
<template lang="pug">
  //- .iconfont.icon-a 不知道怎么集成
  .posititon-hold
    .menu-bar(
      :style="{'bottom': ASA.bottom + 'px'}")
      .menu(
        v-for="item,index in menuList"
        :key="index"
        :class="item.style"
        @click="$router.push(`/${item.key}`)"
      )
</template>

<script>
import { getNotchHeight } from '~/plugins/utils'
export default {
  data () {
    return {
      // 用于异形屏自适应
      ASA: {
        top: 0,
        bottom: 0
      }
    }
  },
  computed: {
    /**
     * 渲染数组
     * @return {String}
     */
    menuList () {
      // computed-style
      let common = (item) => {
        return [this.$route.name === item ? 'current' : '', `.iconfont.icon-${item}`]
      }
      // baseDate
      let list = [
        { key: 'A',
          style: common('A') },
        { key: 'B',
          style: common('B') },
        { key: 'C',
          style: common('C') },
        { key: 'D',
          style: common('D') }
      ]
      return list
    }
  },
  mounted () {
    getNotchHeight().then(data => {
      this.ASA = data
    })
  }
}
</script>

<style lang="stylus" scoped>
.posititon-hold
  height 4.9rem
  display flex
  width 100vw
  flex-shrink 0
  .menu-bar
    position fixed
    left 0
    height 4.9rem
    width 100vw
    display flex
    align-items center
    background white
    z-index 9
    box-shadow: 0 .2rem .3rem .4rem rgba(0, 0, 0, .05)
    .menu
      position relative
      flex-grow 1
      text-align center
      color rgba(170, 170, 170, 1)
      font-size 1rem
      .iconfont
        font-size 1.2rem
      &.current
        color rgba(255, 138, 110, 1)
      .message
        position absolute
        width 1.8rem
        height 1.8rem
        line-height 1.8rem
        background-color #FF5D46
        border-radius 50%
        top -0.6rem
        right 1.5rem
        color #ffffff
        font-size 1rem
</style>

组件的使用
<template lang="pug">
  Menu(v-show="isShowMenu")
</template>
<script>
import Menu from './menu'
export default {
  components: {
    // 菜单组件
    Menu
  },
  data () {
    return {
      // 把需要显示menuBar的路由name填入
      showMenuList: ['A', 'demo', 'B', 'C', 'D', 'E']
    }
  },
  computed: {
    /**
     * 是否显示menuBar
     * @return {Boolean}
     */
    isShowMenu () {
      return this.showMenuList.indexOf(this.$route.name) >= 0 && !this.dontShowMenu
    }
  }
}
</script>