背景
微信小程序的 wxml 用来写界面,但是小程序底层实现却没有引入 dom 的思想,所以我们无法用 js 来操作界面的元素,也就无法使用 h5 的下拉插件,例如 iscoll 来实现下拉刷新的功能,幸运的是小程序提供了一个下拉刷新的功能,使用起来很简单,只需要在 app.json 或者 局部 [page].json 文件里面新增一个 enablePullDownRefresh: true
的配置即可开启下拉刷新的功能。
enablePullDownRefresh 缺点
官方提供的下拉刷新功能不适用于 fixed 顶部的交互,例如以下小程序截图
两者都有共同点,固定搜索框或顶部 tab 选项卡(使用 fixed 布局),内容部分可滚动(使用 scroll-view 实现),而 scroll-view 是无法触发 onPullDownRefresh,以下截取官方文档
在滚动 scroll-view 时会阻止页面回弹,所以在 scroll-view 中滚动,是无法触发 onPullDownRefresh
scroll-view
小程序提供了一个 scroll-view 组件,来实现元素可滚动视图区域,要实现竖向滚动,需要固定一个高度,可以通过动态设置 scroll-view 的高度style="height: {{ scrollContainerHeight }}px;"
来实现可滚动
这样上面的布局就算完成了,接下来要处理下拉刷新的功能,目前想到两种解决方法
一、通过设置触发边界 upper-threshold
和 绑定 scrolltoupper
事件来实现,一个明显缺点就是用户在内容滚动到顶部的时候会无意触发刷新操作(只是正常滚动而不是想下拉)
二、监听 scroll-view 的 bindscroll
事件来做处理,这种方法只适用于 ios,因为 ios 有滚动回弹效果 ,先看实现方法,后面再做兼容 android 的,监听 bindscroll
事件
<scroll-view scroll-y style="height: {{ scrollContainerHeight }}px;" class="scroll-container" bindscroll="scrollHandler"><scroll-view>
以下滚动事件处理函数,这里做了一下节流,减少触发的频率,触发时候震动反馈,很简单的代码就可以实现用户下拉触发刷新操作
scrollHandler(e) { if (e.detail.scrollTop < -80 && !this.data.isLoading) { this.setData({ isLoading: true }) wx.vibrateShort(); // 震动反馈 setTimeout(() => { wx.showToast({ title: '更新成功', }) this.setData({ isLoading: false }) }, 2000) }}
android 兼容下拉刷新
android 机由于 scroll-view 组件没有滚动回弹效果,导致无法监听 e.detail.scrollTop
属性为负数的情况 😱,目前想到的方法是结合 onPullDownRefresh
来实现,先在页面 json 文件开启这个功能,**在顶部fixed区域是滑动是可以触发 onPullDownRefresh 事件**
,过滤掉 ios 的情况即可 😀
onPullDownRefresh() { let sysInfo = wx.getSystemInfoSync(), scollContainerHeight; if (/ios/i.test(sysInfo.system)) { wx.stopPullDownRefresh(); } else { setTimeout(() => { wx.stopPullDownRefresh(); wx.showToast({ title: '更新成功', }) }, 2000) }}
整体的运行效果模拟的就是知乎热榜小程序的下拉刷新方案,附上代码地址,有好的方案欢迎提出哈!