小程序滑动切换tab选项卡

小程序中滑动切换页面tab的需求很常见,今天看到一个很棒的方案,转载至:Kelen’s blog

循环渲染数据

小程序有类似vue的写法,但是还有区别的

data: {
  arr: [1,2,3]
}
<view wx:for="{{arr}}">{{item}}</view>

wx:for-item

默认情况下遍历的每一项用item来获取,如果要指定item的名称,可以用wx:for-item

<view wx:for="{{arr}}" wx:for-item="i">{{i}}</view>

wx:key

同vue一样,设置一个key属性可以优化列表渲染,微信也可以设置一个key,如果数组是每一项是唯一的字符串或者数字,可以使用wx:key=”*this”

<view wx:for="{{arr}}" wx:key="*this">{{item}}</view>

如果是对象数组,一般使用唯一值的字段,例如id

data: {
    list: [
        {id: 1, name: 'list1'},
        {id: 2, name: 'list2'}
    ]
}
<view wx:for="{{list}}" wx:key="id">{{item.name}}</view>

进入正题,按照需求定义两个tab选项卡,如果tab选项过多可以使用scroll-view

<view class='flex-row tabbar'>
    <text id="tabitemRecharge" class='tabitem {{activeTabId=="tabitemRecharge"?"tabitem-active":""}}' bindtap='tabclick'>充值记录</text>
    <text id="tabitemConsume" class='tabitem {{activeTabId=="tabitemConsume"?"tabitem-active":""}}' bindtap='tabclick'>消费记录</text>
    <view class='tabindicator' animation="{{indicatorAnim}}"></view>
</view>

<swiper class='scrollview-content' current-item-id='tabitemRecharge' bindchange='tabChange'>
    <swiper-item item-id="tabitemRecharge">
      <scroll-view scroll-y="true" class="tab-content recharge-list">
        <view class='list-item recharge-item' wx:for="{{rechargeList}}" wx:for-item="rItem" wx:key="id">{{rItem.name}}</view>
      </scroll-view>
    </swiper-item>
    <swiper-item item-id="tabitemConsume">
      <scroll-view scroll-y="true" class="tab-content recharge-list">
        <view class='list-item consume-item' wx:for="{{consumeList}}" wx:for-item="rItem" wx:key="id">{{rItem.name}}</view>
      </scroll-view>
    </swiper-item>
</swiper>

tab页面的数据结构如下

data: {
  tabitemConsume: {},        // 存放tab选项卡的rect,键对应的内容swiper-item的item-id
  tabitemRecharge: {},        // 存放tab选项卡的rect,键对应的内容swiper-item的item-id
  activeTabId: null,
  rechargeList: [],
  consumeList: []
}

这里命名属性的方式是可以方便通过swiper-item的item-id来获取对应的tab选项卡的位置信息,例如

var rect = this.data[swiper-item-id];

wx.createSelectorQuery

要实现tab指示器的大小和位置动画,需要测量每个tab的rect(大小和位置)。微信没有提供丰富的dom操作api,但是提供了通过wx.createSelectorQuery来获取节点的信息

onReady() {
  var query = wx.createSelectorQuery().in(this),
    _this = this;

  _this.animation = wx.createAnimation()

  query.select('#tabitemConsume').boundingClientRect(function (rect) {
    _this.setData({
      tabitemConsume: rect
    });
  })


  query.select('#tabitemRecharge').boundingClientRect(function (rect) {
    _this.setData({
      tabitemRecharge: rect
    });
    _this.setActiveTab('tabitemRecharge');
  })

  query.exec();
}

wx.createAnimation

小程序的动画用wx.createAnimation来实现,给元素设置一个animation属性,通过export方法来给animation属性赋值

每次调用export方法都会清空上一次设置动画,举个例子

<view style="width: 20px; height: 4px; background: #333;" animation="{{anim}}"></view>

this.animation = wx.createAnimation({
  timingFunction: 'ease',
  delay: 0
});

// width变成200,x位置移动到100的动画
this.animation.width(200).translate(100, 0).step();

this.setData({
  anim: this.animation.export()
})  

效果如下

tab指示器的动画

通过上面的wx.createAnimation就可以实现指示器的切换效果了

// tab选项卡激活设置动画
setActiveTab(id) {
  var rect = this.data[id];
  if (rect) {
    this.animation.width(rect.width).translate(rect.left, 0);
    this.setData({
      activeTabId: id,        // 激活的swiper视图
      indicatorAnim: this.animation.step().export()
    })
  }
}

tab选项卡内容块

由于要实现滑动切换tab,用swiper来实现横向滑动,scroll-view来实现纵向滚动

swiper组件

swiper是滑块视图容器组件,可以用来实现幻灯片轮播效果等等。

<swiper class='scrollview-content' current-item-id='{{activeTabId}}' bindchange='tabChange'>
    <swiper-item item-id="tabitemRecharge"></swiper-item>
    <swiper-item item-id="tabitemConsume"></swiper-item>
</swiper>

swiper有一个current-item-id属性,通过匹配swiper-item的item-id属性来设置swiper指定的视图内容,在bindchange事件获取视图的id指定对应的swiper的视图即可

tabChange(e) {
  var id = e.detail.currentItemId;
  this.setActiveTab(id);
}

** 附上效果地址**

不做剽窃别人成果的人,再次注明来源:Kelen’s blog,感谢作者。

发表评论
评论
小俊回复
2019-04-29 00:07Windows 10ChromeIP:广东
牛逼
Tengfei回复
2019-05-19 21:43macOSChromeIP:北京
不错
repostone回复
2019-05-25 16:24Windows 8.1ChromeIP:湖南
好吧,也是转载。
vultr回复
2019-07-28 08:49Windows 8.1ChromeIP:江苏
学习了 感谢分享
VPS234主机测评回复
2019-09-14 21:09Windows 10ChromeIP:四川
说实话微信小程序这个开发框架腾讯做得蛮好的,就是一些功能还不够强大,和APP比起来还是有一定的差距
rantrism回复
2021-12-24 16:08Windows 10ChromeIP:广东
您好~我是腾讯云+社区的运营,关注了您在分享的技术文章,觉得内容很棒,我们诚挚邀请您加入腾讯云自媒体分享计划。完整福利和申请地址请见:https://cloud.tencent.com/developer/support-plan 作者