前言

很多小程序、app都有这种设计:

成果1.将导航栏固定在页面顶部。

成果2.点击导航栏,页面主动滚动到对应内容地位。

成果3.滚动页面主动切换至对应导航栏

成果演示:

代码:
wxml

<!-- 导航栏 --><view class="topView">  <scroll-view class="tabs" scroll-x="true" scroll-with-animation='true' scroll-into-view="x{{xId}}">    <view class="tab {{xId==item.id?'greenColor':''}}" wx:for="{{list}}" wx:key="item" data-id="{{item.id}}"      catchtap="changeTab" id="x{{item.id}}">      <view class="tab_text">{{item.title}}</view>      <view class="tab_line {{xId==item.id?'greenBg':''}}"></view>    </view>  </scroll-view></view><view style="height:80rpx"></view><!-- 滚动内容 --><scroll-view class="columns" scroll-y="true" scroll-with-animation='true' scroll-into-view="f{{yId}}"  style='height:{{height}}rpx;' bindscroll="scrollFloor">  <view class="column " wx:for="{{list}}" wx:key="item" id="f{{item.id}}">    <view class="column_title">{{item.title}}</view>    <view class="column_imgs">      <view class="img_div" wx:for="{{item.photo}}" wx:for-item="items" wx:key="items">        <image src="{{items}}" mode="aspectFill"></image>      </view>      <view class="img_div" wx:if="{{item.photo.length>7}}">        <view class="showMore">点击查看更多</view>      </view>    </view>  </view>  <view style="height:200rpx"></view></scroll-view>

属性解释:

scroll-x="true": 容许横向滚动,反之 scroll-y="true" 容许纵向滚动。

scroll-with-animation:在设置滚动条地位时是否应用动画过渡。

scroll-into-view:滚动到哪个元素(值应为某子元素id【id不能以数字结尾】,例如本文的:id="x{{item.id}}" 或 id="f{{item.id}}" 设置哪个方向可滚动,则在哪个方向滚动到该元素)。

bindscroll:内容滚动时触发的事件。

wxss

.greenColor {  color: rgb(59 185 80);}.greenBg {  background-color: rgb(59 185 80);}.topView {  position: fixed;  top:0rpx;  left:0rpx;  z-index:999;  width:100%;  background-color: #fff;  height: 80rpx;}/* 导航tab */.tabs {  white-space: nowrap;  padding-left: 32rpx;  width: 100%;  overflow: hidden;}/* 暗藏scroll-view页面滚动条 */::webkit-scrollbar {  width: 0;  height: 0;  color: #fff;  display: none;}.tabs .tab {  display: inline-block;  padding-right: 50rpx;}.tab_text {  height: 50rpx;  line-height: 50rpx;  padding-bottom: 10rpx;}.tab_line {  margin: 0 auto;  width: 30rpx;  height: 5rpx;}/*滚动内容*/.column {  width: 100%;  box-sizing: border-box;  overflow: hidden;}.column .column_title {  padding: 40rpx 32rpx 0rpx 32rpx;}.column .column_imgs {  padding: 0 28rpx;  overflow: hidden;  margin-top: 15rpx;}.column_imgs .img_div {  width: 230rpx;  height: 190rpx;  padding: 7rpx 7rpx;  box-sizing: border-box;  float: left;  display: -webkit-flex;  -webkit-flex-wrap: nowrap;  flex-wrap: nowrap;}.column_imgs .img_div image {  width: 100%;  height: 100%;  background: #b5b5b5;}.column_imgs .img_div .showMore {  width: 100%;  height: 100%;  background: #f3f5f8;  line-height: 190rpx;  text-align: center;  font-size: 28rpx;  color: #0f0d6b;}

js

Page({  data: {    height: 0,         //页面高度 rpx    ratio: 0,          //rpx,px转化比    xId: 1,           //x轴选中项    yId: 1,           //y轴滚动地位    heightArray: [],    list: [{        id: 1,        title: "特色",        photo: [          "图片url",          "图片url",          "图片url"        ],      },      {        id: 2,        title: "楼盘",        photo: [          "图片url",          "图片url"        ],      },      {        id: 3,        title: "样板房",        photo: [          "图片url",          "图片url"        ],      },      {        id: 4,        title: "周边配套",        photo: [          "图片url",          ""        ],      },      {        id: 5,        title: "售楼处",        photo: [          "图片url",          "图片url"        ],      },      {        id: 6,        title: "楼盘证件",        photo: [          "t图片url",          "图片url"        ],      },    ]  },  onLoad: function (options) {    let that = this    wx.setNavigationBarTitle({      title: '相册页'    })    //1. 获取页面高度    wx.getSystemInfo({      success: function (res) {        let width = res.windowWidth        let ratio = 750 / width        let height = ratio * res.windowHeight        that.setData({          height: height, //单位rpx          ratio: ratio        })      }    })  },  onShow: function () {    let that = this,      heightArray = [];    //1.获取滚动元素间隔顶部地位-y    setTimeout(function () {      let query = wx.createSelectorQuery() //创立节点查询器      query.selectAll('.column').boundingClientRect(function (rect) {        rect.forEach(function (value) {          heightArray.push((value.top - (170 / that.data.ratio)))        })        that.setData({          heightArray        })      }).exec()    }, 1000) //此处最好用延时,否则获取的后果有可能是null,也有可能值不精确。   },//切换tab导航栏  changeTab: function (e) {    let that = this    let id = e.currentTarget.dataset.id    that.setData({      xId:id,      yId:id,    })  },  //监听滚动 切换tab  scrollFloor: function (e) {    var that = this    var scrollTop = e.detail.scrollTop //滚动条间隔顶部    var heightArray = that.data.heightArray //滚动项间隔顶部    var id = null    //计算比拟得出下标    for (let i = 0; i <= heightArray.length; i++) {      if (scrollTop >= heightArray[i] - 90 && scrollTop < heightArray[i + 1]) {        id = that.data.list[i].id      }    }    that.setData({      xId: id    })  },})

思路

成果1 导航栏悬浮:
父盒子class="topView" 包裹scroll-view 导航栏,父盒子款式属性
.topView {
position: fixed;
top:0rpx;
left:0rpx;
z-index:999;
width:100%;
background-color: #fff;
height: 80rpx;
}
留神:
1.z-index进步层级,防止被滚动内容笼罩。
2.宽度肯定要设置,不然会顶部tab栏将无奈左右滑动。
3.scroll-view 组件应用:white-space: nowrap;overflow: hidden; 并且其子元素设置 :display: inline-block;

成果2 点击导航栏,页面主动滚动到对应内容地位:

导航栏绑定点击事件changeTab,并通过data-id把以后tab的元素的id值传给事件,扭转xId(导航栏选中项)和yId(滚动内容选中项)的值。

成果3 滚动页面主动切换至对应导航栏:

1、页面onLoad时获取页面高度并赋值给 scroll-view 的 style:height款式属性。
2、onShow时获取scroll-view 内子元素间隔顶部间隔并顺次保留在heightArray数组中。
3、页面滚动触发scrollFloor事件,获取scroll-view 整个滚动框间隔顶部的间隔scrollTop,遍历heightArray,如果scrollTop介于heightArray[i]和heightArray[i+1]之间,则阐明页面曾经滚动至i元素,把i元素的id赋值给xId。

小结
以上便是我对这个性能的了解跟实现办法,代码均已给出,各位同学有疑难或者有其余解决方案,欢送沟通探讨!!!