标签栏实现功能:
- 页面向下滑动,标签栏吸顶。
- 点击标签项,标签项呈现选中态,并切换到对应的面板。
- 在面板中进行滑动,可切换标签项和面板。

<!-- tabs.wxml -->
<wxs module="touch" src="./touch.wxs"></wxs><view class="tabs"><view class="tab-navs"><view class="tab-nav" wx:for="{{tabs}}" wx:key="index"><!-- 通过对比 index 与当前点击的标签项的下标来实现选中态 --><view class="tab-label {{currentTabIndex === index ? 'active-tab-label' : ''}}" data-index="{{index}}" bindtap="handleTabChange">{{item}}</view><view class="tab-divider" wx:if="{{currentTabIndex === index}}"></view></view></view><!-- 滑动切换面板 --><view class="tab-panel" bindtouchstart="{{touch.handleTouchstart}}" bindtouchend="{{touch.handleTouchend}}"></view>
</view>
// tabs.js
Page({data: {tabs: ['全部', '待付款', '待发货', '待收货', '售后'],currentTabIndex: 0, // 记录当前点击的标签项的下标},// 点击标签项切换到对应的面板// 快速点击标签项,可能会导致面板中渲染出来的请求数据错乱。原因是:事件和网络请求都是异步的,快速触发事件无法保证它的执行顺序和触发顺序一致,而且,也无法保证网络请求返回数据的顺序和触发顺序一致。因此使用节流函数防止频繁触发调用(节流函数此处不做具体实现,可查看事件稀释一文)。handleTabChange: throttle(function(e) {const {index} = e.target.datasetconst {currentTabIndex} = this.dataif (index === currentTabIndex) returnthis.setData({currentTabIndex: index})}, 500),// 逻辑层和视图层的通信以及页面的重新渲染,性能开销极大。因此,不直接在 js 中监听滑动事件,而是使用 WXS 函数用来响应小程序事件,让事件在视图层响应,从而减少通信的次数和页面的重新渲染达到性能的优化。// 根据滑动方向切换面板handleTouch(values) {const {direction} = valuesconst {tabs, currentTabIndex} = this.dataconst target = currentTabIndex + direction// 越界判断if (target < 0 || target > tabs.length - 1) returnthis.setData({currentTabIndex: target})}
})
// touch.wxs
var touchStart
function handleTouchstart(e) {// 记录触摸开始的 X 轴的位置touchStart = e.changedTouches[0].clientX
}function handleTouchend(e) {// 记录触摸结束的 X 轴的位置var touchEnd = e.changedTouches[0].clientX// 负数表示手指向左滑动,正数表示手指向右滑动var distance = touchEnd - touchStart// 定义滑动方向。-1:页面后退(向右滑动);0:不动;1:页面前进(向左滑动)var direction = 0// 设置一个阈值,超出才切换面板var threshold = 30if (distance < -threshold) {direction = 1} else if (distance > threshold) {direction = -1}if (direction !== 0) {// 调用引用该 wxs 的组件的方法,传递滑动方向e.instance.callMethod('handleTouch', {direction: direction})}
}module.exports = {handleTouchstart: handleTouchstart,handleTouchend: handleTouchend,
}
/* tabs.wxss */
.tabs {width: 100%;// 不能设置父元素的 height 为 100%,否则当页面滑动到一定高度之后 sticky 属性会失效。标签项不再吸顶被顶走。// 原因:和粘性定位的原理有关,在实现吸附效果时,会根据父元素的大小来进行定位。如果设置父元素高度为 100%,那么就会按照这个高度来定位,但是页面中的数据是分页加载的,父元素的高度会越来越高,那么初始计算出的定位就是错误的。// 解决方法:设置 min-heightmin-height: 100%;display: flex;flex-direction: column;
}.tab-navs {display: flex;// 设置粘性定位position: sticky;top: 0;z-index: 99999;
}.tab-nav {flex: 1;display: flex;flex-direction: column;align-items: center;padding: 20rpx 0;
}.tab-label {color: #333333;white-space: nowrap;
}.active-tab-label {color: #FF4A2F;
}.tab-divider {width: 40rpx;height: 5rpx;background-color: #FF4A2F;margin-top: 10rpx;
}.tab-panel {flex: 1;
}

















