前言
众多类似商城项目中,都会有列表分类标签随着界面滚动吸顶的效果
APP中实现相关功能很容易,h5也可以动态操作DOM来设置
微信小程序没有DOM,该怎么实现呢?
思考
其实这个场景还是比较简单的,正常情况下导航标签是在列表中间的,滑到顶部时吸顶,再拉下来时又回到原来的位置
根据场景,有两个参考思路:
1、顶部定位一个常在的同样的导航标签,通过页面的scrollOffset
来控制显隐即可
2、通过动态添加fixed
样式,来动态改变标签在页面中的位置
ps:不过第二种思路会有一个缺陷就是切换位置时页面会因为少了一部分而上移,所以还是需要补白,所以还是用第一种思路
实现
我这里是用了自定义导航栏的,所以实现上会有所不同,如果是用系统导航栏可以稍微调整一下,因为偏移量会有所区别
<!--index.wxml-->
<navigationBar id="navigationBar" title="Test" back="{{false}}"></navigationBar>
<navigator wx:if="{{isFixed}}" class="tabBar fixed" style="top: {{topPadding}}px;">我是标签导航</navigator>
<view class="head_content">我是头部内容</view>
<view class="tabBar">我是标签导航</view>
<view wx:for="{{list}}" wx:key="index" class="list_item">{{item}}</view>
CSS部分
.head_content {
height: 300px;
background-color: orange;
}
.list_item {
height: 100px;
border-bottom: 1px solid #eee;
}
.tabBar {
height: 50px;
background-color: #fff;
border-bottom: 1px solid #00a4ff;
}
.fixed {
position: fixed;
left: 0;
width: 100%;
}
JS部分
Page({
data: {
list: [1,2,3,4,5,6,7,8,9,10],
isFixed: false,
fixedTop: 0
},
onLoad: function () {
this.setData({
topPadding: CacheUtil.naviStatuHeight
})
let query = wx.createSelectorQuery();
query.select(".tabBar").boundingClientRect((res) => {
this.setData({
fixedTop: res.top - CacheUtil.naviStatuHeight
})
}).exec()
},
onPageScroll: function (e) {
if (e.scrollTop > this.data.fixedTop) {
this.setData({ isFixed: true })
} else {
this.setData({ isFixed: false })
}
}
})
其中CacheUtil.naviStatuHeight
这个是我应用启动时获取的导航+状态栏高度,X和其他机型还是有所区别,如果是系统导航栏的话这些相关逻辑都可以省略
这里为什么用navigator而不用view呢?
因为navigator是原生组件,可以在最上层,因为有可能列表内容有原生组件的话滑动就会有问题,所以navigator在不设置url的情况下和view的效果差不多,故采用navigator
cover-view:bug: 自定义组件嵌套 cover-view 时,自定义组件的 slot 及其父节点暂不支持通过 wx:if 控制显隐,否则会导致 cover-view 不显示,而且使用的版本限制也很多,所以就不考虑