components/nav/nav.vue

<template>
    <div class="ion-nav"
         :class="[
           menuContentClass,
           menuContentTypeClass,
           menuContentSideeClass,
           {'menu-content-open':isMenuOpen}]">
        <div nav-viewport></div>
        <div v-if="isMenuOpen" @click="tapToCloseMenu" class="click-cover"></div>
        <!--animate-->
        <transition :name="pageTransitionName">
            <slot></slot>
        </transition>
        <div class="nav-decor"></div>
    </div>
</template>
<style lang="scss">
    .ion-nav {
        .click-cover {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            z-index: 9999;
        }
    }
</style>
<script type="text/javascript">
  /**
   * @component Nav
   * @description
   *
   * ## 基础组件 / Nav组件
   *
   * 这里是Page组件的父容器, 而且转场动画也是在这里执行.
   *
   * 转场动画是使用css3的特性完成的, 也就是说Vimo不提供手势转场动画. 按照在props中的说明, 可提供这几类已写好的专场动画, 如果项目需要定制, 则特换自定义的动画即可, 动画定义在App组件的文件夹中.
   *
   * ### 转场动画
   *
   * 动画是在Nav组件设置的, 其中, IOS默认使用```fade-right-transition```动画, 安卓默认使用```zoom-transition```.
   *
   * ### 页面切换是否需要Indicator的问题
   *
   * 添加这个功能是因为在有些使用情况下, 跳转加载大页面时会有很长时间的空白无交互期, 因此加上Indicator给用户提示正在下载将要去的页面的资源, 这个默认不开启.
   *
   * @props {String} [pageTransition] - 转场动画的名称, 可以是这里的一种: ios-transition / zoom-transition / fade-bottom-transition / fade-right-transition / fade-transition
   * @props {Boolean} [showIndicatorWhenPageChange=false] - 页面切换是否显示Indicator
   *
   * */
  export default {
    name: 'vm-nav',
    props: {
      // 转场动画名称
      // ios-transition/fade-bottom-transition/zoom-transition/fade-right-transition/fade-transition
      pageTransition: {
        type: String,
        default () { return this.$config && this.$config.get('pageTransition') }
      },
      // 转场是否开启Indicator
      showIndicatorWhenPageChange: {
        type: Boolean,
        default () { return this.$config && this.$config.getBoolean('showIndicatorWhenPageChange') }
      }
    },
    data () {
      return {
        // ----------- Nav -----------
        pageTransitionName: null,
        IndicatorComponent: null,

        // ----------- Menu -----------
        isMenuOpen: false, // ion-menu开启
        menuId: null, // menuId
        menuType: '', // overlay/reveal/push  这里只处理 reveal/push
        menuSide: 'left', // 方向
        menuContentClass: null,
        menuContentTypeClass: null,
        menuContentSideeClass: null
      }
    },
    methods: {
      // -------- Nav --------
      /**
       * 初始化导航
       * @private
       * */
      initNav () {
        if (!this.$router) return
        // nav 动画切换部分
        const vm = this
        this.$router.beforeEach((to, from, next) => {
          vm.pageTransitionName = `${vm.pageTransition}-${vm.$history.getDirection()}`
          vm.$app && vm.$app.setEnabled(false, 500)
          next()
        })

        // 页面切换显示Indicator
        if (this.showIndicatorWhenPageChange) {
          import('../indicator').then((component) => {
            this.IndicatorComponent = component.default
            this.$router.beforeEach((to, from, next) => {
              if (vm.$history.getDirection() === 'forward') {
                this.IndicatorComponent.present()
              }
              next()
            })
            this.$router.afterEach(() => {
              if (vm.$history.getDirection() === 'forward') {
                this.IndicatorComponent.dismiss()
              }
            })
          })
        }
      },

      // ----------- Menu -----------
      /**
       * 点击nav关闭Menu
       * @private
       * */
      tapToCloseMenu () {
        this.$nextTick(() => {
          this.isMenuOpen && this.$menus.close()
        })
      },

      /**
       * 设置Menu的信息
       * @private
       * */
      setMenuInfo (menuId) {
        if (menuId) {
          this.menuId = menuId
          this.menuSide = this.$menus.menuIns[menuId].side
          this.menuType = this.$menus.menuIns[menuId].type
          this.menuContentClass = `menu-content`
          this.menuContentTypeClass = `menu-content-${this.menuType}`
          this.menuContentSideeClass = `menu-content-${this.menuSide}`
        }
      },

      /**
       * 初始化menu组件对应的监听处理
       * @private
       * */
      initMenu () {
        // 监听menu的组件事件
        this.$eventBus.$on('onMenuOpen', (menuId) => {
          this.setMenuInfo(menuId)
          this.isMenuOpen = true
        })
        this.$eventBus.$on('onMenuClosing', () => {
          this.isMenuOpen = false
        })
        this.$eventBus.$on('onMenuClosed', () => {
          this.menuContentTypeClass = null
        })
      }
    },
    created () {
      // 初始化menu组件对应的监听处理
      this.initMenu()

      //  初始化导航
      this.initNav()
    }
  }
</script>