1.0.2 • Published 4 years ago

swiper-tab-qiang-shen v1.0.2

Weekly downloads
1
License
ISC
Repository
-
Last release
4 years ago

记一次小程序的tab切换组件说明

前言

记一次在工作中封装的组件 原因:面向百度编程失败

场景需求:

npm.io 设计图如上

  • 1 三个tab,可点击切换,可左右滑动切换
  • 2 每个tab的list高度不同,切换时需计算每个list的高度并且赋值给swiper容器(左右滑动功能在这里用swiper容器实现)
  • 3 吸顶,并且吸顶式tab颜色变为白色

开始

wxml部分

<view id="order">
	<view class="swiper-tab swiper-head" style="background:{{sticky_bg}};top:{{sticky_top}};position:{{position_status}};">
		<block wx:for="{{tab_head}}" wx:key="index">
			<view class="swiper-tab-item swiper-int-item {{currentTab==index?'active':''}} " data-current="{{index}}" bindtap="clickTab">
				{{item.text}}

			</view>
		</block>
	</view>
	<swiper style="height:{{swiper_height}}" class="swiper-body" current="{{currentTab}}" data-tab="{{currentTab}}" duration="300" bindchange="swiperTab">
		<block wx:for="{{tab_head}}" wx:key="index">
			<swiper-item>
				<view id="{{'tab_'+index}}">
					<slot name="{{'tab_'+index}}"></slot>
				</view>
			</swiper-item>
		</block>
	</swiper>
</view>

wxss部分

.swiper-tab {
  width: 100%;
  text-align: center;
  line-height: 90rpx;
  display: flex;
  flex-flow: row;
  justify-content: space-between;
  position: sticky;
  z-index: 99999;
  background: #ffffff;
}
.swiper-tab-item {
  width: 30%;
  color: #434343;
  font-size: 28rpx;
  position: relative;
  flex: 1;
}
.active {
  color: #333333;
  font-size: 34rpx;
  font-weight: bold;
}
.swiper_style {
  text-align: center;
  background-color: #fff;
}
.tab_bg_icon{
  position: absolute;
  top: 46rpx;
  left: 70rpx;
  width: 120rpx;
  height: 24rpx;
  z-index: -1;
  visibility: hidden;
}

wxml和wxss 不再过多描述,大致效果图如下

npm.io

问题及可能出现的纠结点:

  • 1 何时获取swiper下的list高度及赋值给swiper容器的时机
  • 2 吸顶时如何判断背景颜色的变化时机
  • 3 tab切换时,如何让每块list内容回到顶部第一条数据

问题1解决方式:获取高度方法如下:

/**
* @description: 用于计算每个tab对应的list部分的高度,并给整个swiper区域赋值,因为每个swiper容器的高度都是相等的,如果不进行高度的计算,将会无法看到短区域的数据
* @params: currentTab:传入的tab对应的顺序数字
* @return {type} 
*/
getHeight(currentTab) {
  let query = wx.createSelectorQuery().in(this);
  query.select('#tab_' + currentTab).boundingClientRect(rect => {
    let height = rect.height;
    this.setData({
      swiper_height: height + 20 + 'px'
    })
  }).exec();
},

注意:

  • 官网:SelectorQuery wx.createSelectorQuery()返回一个 SelectorQuery 对象实例。在自定义组件或包含自定义组件的页面中,应使用 this.createSelectorQuery() 来代替。(就是在组件中使用时加.in(this);
  • 这个api一定要在页面实例呈现后获取,并且速度较慢(真机调试效果快与微信开发者工具)(这里,如果list的数据时通过接口返回,就需要在接口返回之后再调用getHeight()),如我在工作中的例子 npm.io 三个tab的list数据都是从接口中返回拿到,我会在每个接口数据返回后再去getHeight() (根据实际业务不同,也可以考虑getHeight()的时机)
//当季热门
goodsCommonModel.getHotelList(hotel_param).then(res => {
  this.setData({
    hotelList: that.data.hotelList.concat(res.data.body)
  })
  // 判断上拉加载资源是否小于pageSize
  if (res.data.body.length < 10) {
    this.setData({
      refresh: false
    })
  }
  that.selectComponent('#swiper-list').getHeight(that.data.currentTab)
})

问题2解决方式:监听pageScroll事件,计算页面滚动的距离是否大于swiperTop()每次tab切换后需要回滚的距离)大于时就显示吸顶背景色变为白色

npm.io swiperTop:指tab回滚到吸顶位置的距离,如上图中绿色实线的距离

  • 问题:swiperTop如何获得,方法如下:
getDefaultSwiperTop() {
  var query = wx.createSelectorQuery();
  query.select('#swiper-list').boundingClientRect(rect => {
    console.log(rect)
    if (rect) {
      let top = rect.top
      this.setData({
        swiperTop: top - 100 //100为估计距离,应为头部搜索和导航头的高度相加
      })
      // console.log('清楚定时')
      clearInterval(this.data.timer)
      this.setData({
        timer: null
      })
    }


  }).exec();
},

使用时机:在页面数据全部呈现后计算,也就是在接口数据返回渲染后

 // 每次开启定时器前都先判断是否已存在定时器,若存在就清楚
  this.clearTimer()
  // 这里加定时器是为了防止获取高度失败,因为小程序渲染页面速度过慢导致
  let timer = setInterval(() => {
    that.getDefaultSwiperTop()
  }, 2000)
  this.setData({
    timer: timer
  })

注意:页面渲染需要一定的时间,getDefaultSwiperTop必须在页面渲染完成后执行,所以可能会出现获取失败情况,我这里是通过定时器,不停的获取,一旦获取成功,就立即清除定时器,目前没有找到更好的解决办法

问题3解决方式

 wx.pageScrollTo({
  scrollTop: this.data.swiperTop + 1
});

组件项目地址:https://github.com/obaqiang/mine-weixin.git