参照饿了么小程序店铺详情的页面交互效果实现,先看一下小程序的效果
这里把功能点拆分为以下5点:
1.滚动时左侧分类联动
2.点击左侧分类时右侧跳到对应的商品分类下
3.商品左侧分类滚动固定效果
4.右侧商品分类的固定效果
5.左侧分类可以单独滚动
首先设计页面布局,从小程序右上角的滚动条与整体滚动效果可以发现,整体是有一个一屏的滚动盒子的,在小程序中我们使用scroll-view组件来实现
然后左侧分类也是可以单独滚动的,首先画出布局。点这里看效果
功能1:滚动时左侧分类联动
页面滚动时需要与左侧的分类联动,分为以下几步实现
1.获取每个分类的位置集合
initDomHeight() {
// 获取所有分类的位置集合
const domCates = document.querySelectorAll('.section-title') || []
var list = Array.from(domCates)
if (list.length === 0) return
this.cateHeightList = []
list.forEach(item => {
this.cateHeightList.push(item.offsetTop)
})
}
2.监听滚动事件
...
this.throttleScroll = lodash.throttle(this.handleScroll, 60)
...
initEvent() {
const el = document.querySelector('.phone')
if (!el) return
this.pageCtx = el
el.addEventListener('scroll', (e) => {
this.throttleScroll(e.target.scrollTop)
}, false)
}
...
3.计算当前滚动位置所属于于哪个分类
在小程序开发时,我们需要使用微信的API:wx.createSelectorQuery() 获取到分类的高度集合,需要注意的是这里是数据动态渲染之后才能获取到节点的位置与高度
在wepy放到this.$nextTick()中去执行
2.滚动事件监听,我们使用scroll-view的bindscroll事件,由于scroll事件会频繁的触发,所以这里我们给scroll事件加一个节流throttle函数,频繁触发时60毫秒执行一次
...
// top:当前滚动的距离
handleScroll(top) {
const { cateHeightList } = this
cateHeightList.forEach((item, index) => {
if (Number(top) >= Number(cateHeightList[index]) && Number(top) < Number(cateHeightList[index + 1])) {
if (this.activeCateIndex !== index) this.activeCateIndex = index
}
})
}
...
功能2:点击左侧分类时右侧跳到对应的商品分类下
这个功能类似锚点链接的功能,点击跳转到页面对应位置,在小程序的scroll-view中有相应的参数支持该功能,参数【scroll-into-view】,使用说明如下:

功能3:商品左侧分类滚动固定效果
功能4:右侧商品分类的固定效果
这两个功能效果类似,都是滚动时固定在页面顶部。
实现滚动固定的效果,这里有两个方案
方案一:使用fixed定位,通过滚动监听动态添加fixed效果
方案二:使用css3的striky属性
方案一在实践过程中发现一个难以解决的问题: 在小程序的scroll-view中使用fixed定位无效,会跟随页面滚动,官方建议解决方案是把fixed定位的元素放到scroll-view外面
但是这样改动会改变整个页面的结构,因此我们另辟蹊径,选择通过方案二去实现该功能,而stricky属性针对这种滚动fixed的场景非常适用。戳这里看效果
由于是CSS3的属性,需要考虑到兼容性问题
可以看到除了IE与Opera Mini外,其他的基本都支持该属性,需要注意的是Safari部分版本需要加-webkit-的前缀
需要注意的是,striky属性的效果会受父级元素overflow属性的影响,若该属性未生效,可以检查父级元素中是否包含了overflow: hidden属性,去掉即可
其他更多情况可以参考 张鑫旭老师的 深入理解position sticky粘性定位的计算规则
功能5:左侧分类可以单独滚动
这里给左侧的分类加一个scroll-view容器即可。考虑到如果左侧选中的分类不在当前可视区域内时用户无法看到左侧当前选中的分类,所以这里加了使用scroll-view之后,也可以像右侧的分类一样加一个【scroll-into-view】属性
在更新当前选中分类时,使得高亮的分类始终在可视区域内
页面demo 点这里