微信小程序实现顶部标签栏

博客介绍了微信小程序标签栏的实现功能,包括页面下滑时标签栏吸顶,点击标签项呈现选中态并切换对应面板,在面板中滑动也可切换标签项和面板。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

标签栏实现功能:

  1. 页面向下滑动,标签栏吸顶。
  2. 点击标签项,标签项呈现选中态,并切换到对应的面板。
  3. 在面板中进行滑动,可切换标签项和面板。
    请添加图片描述
<!-- 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.dataset
    const {currentTabIndex} = this.data
    if (index === currentTabIndex) return
    this.setData({currentTabIndex: index})
  }, 500),
  // 逻辑层和视图层的通信以及页面的重新渲染,性能开销极大。因此,不直接在 js 中监听滑动事件,而是使用 WXS 函数用来响应小程序事件,让事件在视图层响应,从而减少通信的次数和页面的重新渲染达到性能的优化。
  // 根据滑动方向切换面板
  handleTouch(values) {
    const {direction} = values
    const {tabs, currentTabIndex} = this.data
    const target = currentTabIndex + direction

    // 越界判断
    if (target < 0 || target > tabs.length - 1) return

    this.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 = 30
  if (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-height
  min-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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值