微信小程序原生代码,自定义导航栏+tabs吸顶+锚点

最新优化动态内容,滑动tabs选项定位不准确问题,以及性能问题

效果图

 需求说明:在产品详情页较多。 例如刚进入页面自定义导航栏为空(图一), 当滑动到tabs吸顶后自定义导航栏出现(图二), tab点击锚点跳转。使用scroll-view 跟 scroll-into-view,虽然可以完成锚点跳转,但是会页面锚点直接顶到顶部。

                                           

                                 图一                                                                        图二

 使用到的API:

        wx.pageScrollTo

        wx.createSelectorQuery

Github地址:https://github.com/Dgg1997/tabs-sticky

所有代码:

        wxml:

<view wx:if="{{scrollTopNew + navT+navH >= stickyTopHeight}}" style="width: 100%;height: {{navT+navH}}px;background: #fff;position: fixed;z-index: 999;top: 0;display: flex;justify-content: center;">
  <text style="margin-top: {{navT}}px;line-height: {{navH}}px;">产品详情</text>
</view>

<!-- 占位 -->
<view class="top-main"></view>

<view class="tabs" id="tabs" style="{{oneFixed}}">
  <block wx:for="{{list}}" wx:key="index">
    <view id="{{index}}" bindtap="tabChange" class="tab-item tab-item-{{index}} {{ index== currentIndex ? 'active' : ''}}" data-index="{{index}}" data-key="{{ item.key }}">
      {{item.title}}
    </view>
  </block>
</view>

  <view class="indexConDecOut" id="cont0">
  产品
  </view>
  <view class="indexConDecOut" id="cont1">
  团期
  </view>
  <view class="indexConDecOut" id="cont2">
  行程
  </view>
  <view class="indexConDecOut" id="cont3">
  费用
  </view>

        JS代码

const app = getApp();
const utils = require('../../utils/util')
Page({
  data: {
    scrollTopNew: 0,  //滚动距离
    stickyTopHeight: 0, //tabs距离顶部的高度
    navT: 0,  //自定义导航栏距离顶部margin-top
    navH: 0,   //自定义导航栏行高
    oneFixed: '', //吸顶样式
    list: [{   //tabs
        id: 0,
        title: '产品'
      },
      {
        id: 1,
        title: '团期'
      },
      {
        id: 2,
        title: '行程'
      },
      {
        id: 3,
        title: '费用'
      },
    ],
    currentIndex: 0, //当前选中tabs
  },
  tabChange(e) {
    let selector = '#cont' + e.currentTarget.dataset.index
    let offsetTop = 50 + this.data.navT + this.data.navH
    wx.pageScrollTo({
      offsetTop: -offsetTop,
      selector: selector,
      duration: 0,
      success:function(e){
        console.log("成功",e)
      },
      file:function(e){
        console.log("失败",e)
      }
    })
    this.setData({
      currentIndex: e.currentTarget.dataset.index,
    })
  },

  getNav: function () {
    let that = this
    const res = wx.getMenuButtonBoundingClientRect()
    that.setData({
      navT: res.top,
      navH: res.height
    })
  },

  getTopStickyHeight(){
    let that = this
    var query = wx.createSelectorQuery();
    query.select('#tabs').boundingClientRect();
    query.exec(function (rect) {
      that.setData({
        stickyTopHeight: rect[0].top
      })
    })
  },

  onPageScroll: utils.throttle(function (res) {
    let event = res[0]
    let that = this
    let scrollTopNew = event.scrollTop;
    
    let height = this.data.navT + this.data.navH
    if (event.scrollTop + height > this.data.stickyTopHeight) {
      let fixedStyle = [
        `top:${height}px`,
        'left: 0px',
        'right:0px',
        'position: -webkit-sticky',
        'position: sticky',
        'z-index: 5',
        'width: 100%',
        'background: #fff'
      ].join(';');
      that.setData({
        oneFixed: fixedStyle, //添加吸顶类
        scrollTopNew
      })
    } else {
      that.setData({
        oneFixed: '',
        scrollTopNew
      })
    }


    const query = wx.createSelectorQuery()
    for (let item of that.data.list) {
      query.select('#cont' + item.id).boundingClientRect()
    }

    query.exec(function (rect) {
      let currentIndex = 0
      for (let i in rect) {
        if (rect[i].top <= (height + 50)) {
          currentIndex = i
        } else {
          break;
        }
      }
      that.setData({
        currentIndex
      })
    })
  }, 100),

  onLoad(optons) {
    let that = this
    that.getNav()
    that.getTopStickyHeight()
  },
  onShow() {

  },


})

        WXSS代码

.top-main{
  width: 100%;
  height: 1000rpx;
  background-color: aqua;
}

.tabs {
  display: flex;
  align-items: center;
  justify-content: space-around;
  position: relative;
  width: 100%;
  height: 50px;
  box-sizing: border-box;
  font-size: 36rpx;
  border-bottom: 2rpx solid #dee3f0;
  z-index: 9;
}
.tabs .tab-item {
  color: #666666;
  display: inline-block;
  position: relative;
  text-align: center;
  font-size: 36rpx;
  padding: 0 20rpx;
}
.tabs .tab-item.active {
  font-size: 36rpx;
  color: #333333;
  font-weight: bold;
}
.tabs .tab-item:after {
  content: '';
  display: block;
  height: 8rpx;
  width: 0;
  background: #f6414a;
  position: absolute;
  bottom: -16rpx;
  left: 50%;
  border-radius: 100rpx;
  -webkit-transition: all 0.2s ease-in;
  transition: all 0.2s ease-in;
  -webkit-transform: translateX(-50%);
  transform: translateX(-50%);
}
.tabs .tab-item.active:after {
  right: 0;
  width: 100%;
}

.indexConDecOut{
  width: 100%;
  height: 2000rpx;
}

.scroll {
  height: 100vh;
}

        JSON代码

{
  "navigationStyle":"custom",
  "usingComponents": {}
}

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值