tab/tab.vue

<template>
    <a class="tab-button" ref="routerLink" @click="$_tabClickHandler($event)" :id="tabId" :class="componentClass">
        <Icon :mode="mode" v-if="tabIcon" :name="tabIcon" :isActive="isActive" class="tab-button-icon"></Icon>
        <span v-if="tabTitle" class="tab-button-text">{{tabTitle}}</span>
        <Badge :mode="mode" v-if="tabBadge" class="tab-badge" :color="tabBadgeStyle">{{tabBadge}}</Badge>
    </a>
</template>
<script type="text/javascript">
  /**
   * @component Tabs/Tab
   * @description
   *
   * ## 大标签 / Tab
   *
   * 还是需要再声明下,Tab组件必须和Tabs组件配合使用, Tab组件内部与路由`$router`结合,
   * Tab点击切换使用的是`$router.[this.routerType](this.to)`处理的, 因此应该包含:to属性用于跳转。
   *
   * @props {String} [mode] - Tab组件内Icon核Badge的模式, 不可较差定义不同mode, 默认跟随系统
   * @props {Boolean} [disabled=false] - 是否能选择
   * @props {Object} to - 路由跳转,必填
   * @props {String} [routerType='replace'] - 路由跳转类型: replace/push
   * @props {Boolean} [show=true] - 是否显示, 用于灰度发布等场景
   * @props {String} [tabBadge] - 徽章显示值
   * @props {String} [tabBadgeStyle] - 徽章颜色
   * @props {String} [tabIcon] - tab的IconName
   * @props {String} [tabTitle] - tab的tabTitle
   *
   * @fires component:Tabs#onTabSelect
   *
   * @usage
   * <Tab routerType="replace" :to="{name:'tabsBottom.demoTab3'}" tabBadge="7" tabTitle="Star" tabIcon="star" :disabled="false"></Tab>
   *
   * */
  import Badge from '../badge'
  import Icon from '../icon'

  export default {
    name: 'Tab',
    components: {Badge, Icon},
    props: {
      mode: {
        type: String,
        default () { return this.$config && this.$config.get('mode') || 'ios' }
      },
      // 是否能选择
      disabled: {
        type: Boolean,
        default: false
      },
      // 路由跳转
      to: {
        type: Object,
        required: true,
        validator (obj) {
          return !!obj && (!!obj.name || !!obj.path)
        }
      },
      routerType: {
        type: String,
        default: 'replace',
        validator (val) {
          return ~[
            'replace',
            'push'
          ].indexOf(val)
        }
      },
      // 是否显示
      show: {
        type: Boolean,
        default: true
      },
      tabBadge: [String, Number],         // 徽章显示值
      tabBadgeStyle: String,    // 徽章颜色
      tabIcon: String,          // tab的IconName
      tabTitle: String          // tab的tabTitle
    },
    data () {
      return {
        isActive: false // 这个值具有滞后性, 只代表当前的页面的状态, 不能用于其他
      }
    },
    computed: {
      componentClass () {
        return {
          'has-title': this.hasTitle,
          'has-icon': this.hasIcon,
          'has-title-only': this.hasTitleOnly,
          'icon-only': this.hasIconOnly,
          'has-badge': this.hasBadge,
          'tab-disabled': this.disabled,
          'tab-hidden': !this.show,
          'tab-active': this.isActive
        }
      },
      hasTitle () {
        return this.tabTitle
      },
      tabId () {
        return `tabId-${this._uid}`
      },
      hasIcon () {
        return this.tabIcon
      },
      hasTitleOnly () {
        return this.tabTitle && !this.tabIcon
      },
      hasIconOnly () {
        return this.tabIcon && !this.tabTitle
      },
      hasBadge () {
        return this.tabBadge
      }
    },
    watch: {
      $route () {
        this.$_refreshMatchState()
      }
    },
    inject: ['tabsComponent'],
    methods: {
      /**
       * 当前路由是否匹配当前Tab组件状态
       * @private
       * */
      $_isMatch () {
        return this.to.name === this.$route.name || this.to.path === this.$route.path
      },
      /**
       * Tab点击时动作
       * @private
       * */
      $_tabClickHandler () {
        if (!this.disabled) {
          this.$router && this.$router[this.routerType](this.to)
          /**
           * @event component:Tabs#onTabSelect
           * @description Tab选中时触发
           * @property {string}
           */
          this.$emit('onTabSelect', this)
        }
      },
      $_refreshMatchState () {
        this.isActive = this.$_isMatch()
      }
    },
    created () {
      this.$_refreshMatchState()
    }
  }
</script>