微信小程序自定义tab

1,007 阅读1分钟

1、组件封装

利用微信提供的swiper和swiper-item组件来实现,监听swiper的变化去改变选项,同时也监听选项的变化去改变当前的swiper,双向监听双向变化

wxml

<view class="weui-tabs">
  <!-- 选项 -->
  <view class="weui-tabs-bar__wrp" id="weui-tabs-bar__wrp">
    <scroll-view scroll-x scroll-into-view="item_{{currentView}}" scroll-with-animation="{{animation}}">
      <view class="weui-tabs-bar__content">
        <block wx:for="{{tabs}}" wx:key="title">
          <view id="item_{{index}}" class="weui-tabs-bar__item" style="background-color: {{tabBackgroundColor}}; color: {{activeTab === index ? tabActiveTextColor : tabInactiveTextColor}};" bindtap="handleTabClick" data-index="{{index}}">
            <view class="weui-tabs-bar__title {{tabClass}} {{activeTab === index ? activeClass : ''}}" style="border-bottom-color: {{activeTab === index ? tabUnderlineColor : 'transparent'}}">
              <text class="">{{item.title}}</text>
            </view>
          </view>
        </block>
      </view>
    </scroll-view>
  </view>
  <!-- 内容 -->
  <swiper class="{{swiperClass}}" current="{{activeTab}}" duration="{{duration}}" bindchange="handleSwiperChange">
    <swiper-item wx:for="{{tabs}}" wx:key="title">
      <slot name="tab-content-{{index}}"></slot>
    </swiper-item>
  </swiper>
</view>

js

Component({
  options: {
    addGlobalClass: true,
    pureDataPattern: /^_/,
    multipleSlots: true
  },
  properties: {
    tabs: { type: Array, value: [] },//数据项格式{title:"选项一"}
    tabClass: { type: String, value: '' },//选项卡样式
    swiperClass: { type: String, value: '' },//内容区域 swiper 的样式
    activeClass: { type: String, value: '' },//选项激活时class
    tabUnderlineColor: { type: String, value: '#07c160' },//激活时下划线颜色
    tabActiveTextColor: { type: String, value: '#000000' },//激活时文字颜色
    tabInactiveTextColor: { type: String, value: '#000000' },//未选中时文字颜色
    tabBackgroundColor: { type: String, value: '#ffffff' },//选项卡背景色
    activeTab: { type: Number, value: 0 },//当前激活tab
    animation: { type: Boolean, value: true },//是否使用动画
    duration: { type: Number, value: 500 }//动画过渡时间
  },
  data: {
    currentView: 0
  },
  observers: {
    activeTab(_activeTab) {
      var len = this.data.tabs.length;
      if (len === 0) return;
      var currentView = _activeTab - 1;
      if (currentView < 0) currentView = 0;
      if (currentView > len - 1) currentView = len - 1;
      this.setData({ currentView: currentView });
    }
  },
  methods: {
    handleTabClick(e) {
      var index = e.currentTarget.dataset.index;
      this.setData({ activeTab: index });
      this.triggerEvent('tabclick', { index: index });
    },
    handleSwiperChange(e) {
      var index = e.detail.current;
      this.setData({ activeTab: index });
      this.triggerEvent('change', { index: index });
    }
  }
});

wxss

.weui-tabs{
  width:100%
}
.weui-tabs-bar__wrp{
  width:100%;
  background:#fff;
}
.weui-tabs-bar__content{
  width:100%;
  white-space:nowrap;
}
.weui-tabs-bar__item{
  display:inline-block;
}
.weui-tabs-bar__title{
  display:inline-block;
  border-bottom-width:2px;
  border-bottom-style:solid;
  border-bottom-color:transparent;
  padding-bottom: 4px;
  margin: 0 10px;
  color: rgba(0, 0, 0, 0.9);
}
.tab-bar-title__selected{
  font-size: 20px;
  font-weight: bold;
}

json

{
    "component": true,
    "usingComponents": {}
}

2、使用

json

{
  "usingComponents": {
    "tab":"/com/tabs/index"
  }
}

wxml

<view class="page">
  <tab tabs="{{tabs}}" activeTab="{{activeTab}}" swiperClass="weui-tabs-swiper" bindtabclick="onTabClick" bindchange="onChange" activeClass="tab-bar-title__selected">
    <view class="tab-content" slot="tab-content-0">选项一</view>
    <view class="tab-content" slot="tab-content-1">选项二</view>
    <view class="tab-content" slot="tab-content-2">选项三</view>
    <view class="tab-content" slot="tab-content-3">选项四</view>
    <view class="tab-content" slot="tab-content-4">选项五</view>
    <view class="tab-content" slot="tab-content-5">选项六</view>
    <view class="tab-content" slot="tab-content-6">选项七</view>
  </tab>
</view>

js

Page({
  data: {
    tabs: [],
    activeTab: 0,
  },

  onLoad () {
    const tabs = [
      { title: '选项一', },
      { title: '选项二', },
      { title: '选项三', },
      { title: '选项四', },
      { title: '选项五', },
      { title: '选项六', },
      { title: '选项七', },
    ]
    this.setData({ tabs })
  },

  onTabClick (e) {
    this.setData({ activeTab: e.detail.index })
  },

  onChange (e) {
    this.setData({ activeTab: e.detail.index })
  },
})

wxss

.weui-tabs-swiper{
  height: calc(100vh - 76rpx);
}
.tab-content{
  width: 100%;
  height: 100%;
  overflow: scroll;
}

3、效果

tab.gif