vue项目中原生js实现滑动切换tab选项卡

1,257 阅读2分钟

效果图在上面,直接上代码吧-_-

<!-- 会员和至尊会员tab -->
   <div
      class="member-card-tab-section"
      ref="memberCardTab"
    >
      <div
        v-for="(item, index) in memberTabList"
        :key="index"
        :class="['normal-superme-member', `${index === 0 ? 'normal' : 'superme'}-member`,
          currentIndex === index ? 'bright-color' : 'grey-color']"
        >
        <div
          class="normal-superme-member-text"
          @click="changeTab(index)"
        >
          {{ item }}
          <div
            class="check-line"
            ref="checkLine"
            v-show="currentIndex === index"
          />
        </div>
      </div>
    </div>
 <!-- 滑动切换tab -->
    <div
      class="superme-normal-member"
      @touchstart="touchStart"
      @touchend="touchEnd"
    >
      <div class="member-swiper">
        <ul :style="{'transform': `translateX(${offsetVal}px)`}">
          <li
            v-for="(item, index) in 2"
            :key="index"
            ref="memberItem"
          >
             XXXXXXXXXXXXXXXXXXXXX业务样式代码~
          </li>
        </ul>
      </div>
    </div>
 .superme-normal-member {
    @include position(inherit);
    overflow: hidden;
    margin-bottom: 164px;
    .member-swiper {
      ul {
        white-space: nowrap;
        height: 100%;
        padding: 0;
        transition: all .5s;
        li {
          display: inline-block;
        }
      }
    }
  }
  
 .member-card-tab-section {
    position: absolute;
    left: 0px;
    top: 44px;
    display: flex;
    font-size: 32px;
    font-weight: 500;
    justify-content: center;
    z-index: 2;
    width: 100%;
    .normal-member {
      padding-left: 87px;
    }
    .superme-member {
      padding-right: 87px;
    }
    .normal-superme-member {
      height: 44px;
      line-height: 44px;
      width: 100%;
    }
    .normal-superme-member-text {
      width: 100%;
      position: relative;
      text-align: center;
      .check-line{
        position: absolute;
        left: 124px;
        top: 55px;
        @include backgroundImage(40px, 4px, $imgBaseUrl + '/line.jpg');
      }
    }
    .bright-color {
      color: #BE9F8F;
    }
    .grey-color {
      color: rgba(190, 159, 143, 0.5);
    }
  }

js代码

data(){
  return {
      memberTabList: ['会员', '至尊会员'],
      offsetVal: 0, // 位移
      currentIndex: 0, // swiper目前的索引
      firstTouchX: 0, // 首次位移
      pageLength: 2,
      firstSvipPacket: {}, // 至尊会员第一个套餐
      firstVipPacket: {}, // 普通会员第一个套餐
      packetList: [], // 套餐
      memberTabList: ['会员', '至尊会员'],
      triggerDistance: 50, // 阈值
  }
},
watch: {
  currentIndex (val) {
    this.offsetVal = -(this.$refs.memberItem[0].offsetWidth * val)
  },
},
methods: {
   // 触摸
    touchStart (event) {
      event.stopPropagation()
      this.firstTouchX = parseInt(event.changedTouches[0].clientX)
    },
    touchEnd (event) {
      event.stopPropagation()
      const diff = event.changedTouches[0].clientX - this.firstTouchX
      if (Math.abs(diff) > this.triggerDistance) {
        diff > 0 ? this.prePage() : this.nextPage()
      }
    },
    // 从左往右滑动
    prePage () {
      this.currentIndex === 0 ? this.currentIndex = 0 : this.currentIndex--
    },
    // 从右边往左边滑动
    nextPage () {
      this.currentIndex === (this.pageLength - 1) ? this.currentIndex = 
      (this.pageLength - 1) : this.currentIndex++
    },
    changeTab (index) {
      this.currentIndex = index
    },
}

思路与重点:

  1. ul 里面有两个li进行平铺(display:inline-block), 假设我们默认的是第一张,currentIndex为0, index为0,那么offsetVal就是为0
  1. currentIndex也就是tab目前的index,首次获取肯定是从后台返回,或者产品要求的默认哪个,或者默认第一个,具体看要求
  1. 那么改变currentIndex有两种途径,第一种就是通过点击tab改变,相对应的changeTab方法,第二种是用手滑动,对应触发touchStart,touchEnd
  1. 确定翻页,currentIndex有变化,然后根据currentIndex变化往左或者往右去平移屏幕宽度的一个大小(主要是利用transform:translateX)的特性去做平移动,同时设置transition: all .5s;的过度效果
     const diff = event.changedTouches[0].clientX - this.firstTouchX
      if (Math.abs(diff) > this.triggerDistance) {
        diff > 0 ? this.prePage() : this.nextPage() 
        // diff如果大于0表示,表示从左往右滑动,如果是小于0 表示从右边往左滑动
      }

clientX/Y获取到的是触发点相对浏览器可视区域左上角距离,不随页面滚动而改变。(兼容性:所有浏览器均支持)

这里为什么要对比一个triggerDistance,这是一个阈值,如果不做判断,不管滑动多少距离,都会进行翻页,或者别人只是手机稍作移动,并不想 翻页.所以要他移动一定距离,才进行翻页处理

好好生活-_-