tab-block.vue 2.15 KB
<template>
  <div class="tab-block">
    <div v-for="(tab, index) in tabList" :key="index" :ref="'tab-item' + index" class="tab-item" :class="{active: index == activeIndex}"  @click="changeType(index)">
      <div class="name">{{tab.name}}</div>
      <div v-if="index == statusBlockIndex" ref="statusBlock" class="tab-status-block" :style="statusBlockStyle"></div>
    </div>
  </div>
</template>

<script>
import {findIndex} from 'lodash';

export default {
  props: {
    activeType: {
      type: Number,
      default: 0
    }
  },
  data() {
    let tabList = [
      {name: '最新', type: 2},
      {name: '热门', type: 1},
    ];
    let index = Math.max(findIndex(tabList, {type: this.activeType}), 0);

    return {
      tabList,
      statusBlockIndex: index,
      activeIndex: index,
      statusBlockStyle: {}
    };
  },
  watch: {
    activeType(val) {
      let index = findIndex(this.tabList, {type: val});

      if (index > -1) {
        this.activeIndex = index;
      }
    },
    activeIndex() {
      this.changeStatusBlockStyle();
    }
  },
  methods: {
    changeType(index) {
      this.activeIndex = index;
      this.$emit('on-change-tab', {...this.tabList[index]});
    },
    changeStatusBlockStyle() {
      const baseDom = this.$refs['tab-item' + this.statusBlockIndex];

      if (baseDom) {
        const baseLeft = baseDom[0].offsetLeft;
        const {offsetLeft, offsetWidth} = this.$refs['tab-item' + this.activeIndex][0] || {};

        this.statusBlockStyle = {
          transform: `translate3d(${offsetLeft - baseLeft}px, 0, 0)`,
          width: offsetWidth + 'px'
        };
      }
    }
  }
};
</script>

<style scoped>
.tab-block {
  height: 100px;
  background-color: #fff;
  display: flex;
  justify-content: center;
  font-size: 32px;

  .tab-item {
    margin: 0 38px;
    padding-top: 20px;
    color: #b0b0b0;
    position: relative;

    &.active {
      color: #222;
      font-weight: 500;
    }

    .name {
      margin-bottom: 4px;
    }
  }

  .tab-status-block {
    width: 100%;
    height: 10px;
    background: #d0021b;
    box-shadow: 0 4px 8px 0 rgba(210,0,13,0.34);
    position: absolute;
    transition: all 500ms;
  }
}

</style>