uniapp自定义Tab组件可自动滑动居中

297 阅读1分钟

uniapp开发项目时,组件库的Tab不满足当前业务样式需求,所以自定义Tab组件,但需要点击后自动滑动居中的交互效果; 通过使用uniapp组件scroll-view,改变其scrollLeft的值来实现,代码如下:


<template>
<view class="tab-container">
  <scroll-view
    :scroll-left="scrollLeft"
    scroll-x
    scroll-with-animation
    class="tab-container__scroll-view"
    :show-scrollbar="false"
    ref="tab-container__scroll-view"
  >
    <view class="tab-container__wrapper">
      <view 
        v-for="(item, index) in tabList" 
        :key="item.id" 
        :class="['tab-item ', tabList.length > 2 ? ' over2' : ' max2' , {active: tabActive === index}]"
        @click="onChangeTabHandler(index,item)">{{ item.name }}</view>
    </view>
  </scroll-view>
</view>
</template>

<script>
  export default {
    data() {
      return {
        scrollWidth: 0,
        scrollLeft: 0,
        tabActive: 0,
        tabList: [{
          id: 1,
          name: '111',
        }, {
          id: 2,
          name: '222',
        }, {
          id: 3,
          name: '333',
        }, {
          id: 4,
          name: '444',
        }]
      }
    },
    methods: {
      onChangeTabHandler(index,item) {
        this.tabActive = index;

        if(this.tabList.length > 2) {
          this.$nextTick(() => {
            this.moveTabToMiddle(index)
          });
        }
      },
      moveTabToMiddle(index) {
        const query = uni.createSelectorQuery().in(this)
        query.selectAll('.tab-item').boundingClientRect(data => {
          let _width = 0
          for (let i = 0; i < index; i++) {
            _width += data[i].width
          }

          // 当大于屏幕一半的宽度则滚动,否则就设置位置为0
          const _clientWidth = uni.getSystemInfoSync().windowWidth / 2;
          if (_width > _clientWidth-50) {
            this.scrollLeft = _width + data[index].width / 2 - _clientWidth;
          } else {
            this.scrollLeft = 0;
          }
        }).exec()
      }
    }
  }
</script>

<style lang="scss" scoped>
.tab {
  &-container {
    // width: 100%;
    background-color: beige;
    // display: flex;
    // overflow-x: scroll;
    &__scroll-view {
      // display: flex;
    }
    &__wrapper {
      display: flex;
      // overflow-x: scroll;
    }
  }
  &-item {
    &.max2 {
      width: 50%;
    }
    &.over2 {
      flex: none;
      width: 375rpx;
    }
    &.active {
      background-color: burlywood;
    }
  }
}
</style>`