一、在微信小程序中,想到 下拉刷新 和 上拉加载,若是是整个页面都拖动的话,能够在页面配置中,配置 enablePullDownRefresh 和 onReachBottomDistance 而后在 .js 中 使用 Page.onPullDownRefresh 和 Page.onReachButton 这样来进行。html
二、上面的作法是官方推荐咱们作页面的 下拉刷新 和 上拉加载 所使用的方法。但某种状况好比头部是固定的,但使用上面的方法,整个页面都拉动,会显得很奇怪。这个时候,咱们的滚动其实是使用了 scroll-view 来进行的,会显得更加好看。小程序
三、使用 scroll-view 的话,会想到的是 bindscrolltoupper 和 bindscrolltolower,但其实使用这个两个也仍是会出现问题的。这个问题是 bindscrolltoupper 会触发屡次,并且一开始在顶部的时候,有可能没有响应到。微信小程序
下面的方法是使用 touchstart 和 touchend 来实现的 上拉加载 和 下拉刷新:微信
1 <scroll-view id="scroll-wrap" 2 scroll-y 3 bindtouchstart="start_fn" 4 bindtouchend="end_fn"> 5 // 列表 6 </scroll-view>
一般咱们都写法,都如上面同样,但由于要拿到滚动的最大高度,因此须要写成下面的样式:app
1 <scroll-view id="scroll-wrap" 2 scroll-top="{{scroll_top}}" 3 scroll-y> 4 <view id="inner-wrap" 5 bindtouchstart="start_fn" 6 bindtouchend="end_fn"> 7 // 列表 8 </view> 9 </scroll-view>
咱们须要获取 scroll-wrap 和 inner-wrap 的高度。学习
1 Page({ 2 data: { 3 height: 0, // scroll-wrap 的高度,这个高度是固定的 4 inner_height: 0, // inner-wrap 的高度,这个高度是动态的 5 scroll_top: 0, // 滚动到位置。 6 start_scroll: 0, // 滚动前的位置。 7 touch_down: 0 // 触摸时候的 Y 的位置 8 }, 9 // start: onLoad 生命周期 10 onLoad () { 11 let self = this; 12 wx.createSelectorQuery().select('scroll-wrap').boundingClientReact(function (rect) { 13 self.data.height = rect.height; 14 }).exec(); 15 } 16 // end: onLoad 生命周期 17 });
由于scroll-view 要在垂直方向上能够滚动,须要设置height 的高度,因此一般状况下,只要获取一次就好了,若是scroll-view 由于某个元素消失掉,影响了高度的话,记得要更新 height 的值。优化
接下来就是 bindtouchstart 和 bindtouchend 的配合:动画
bindtouchstart ---- start_fn:this
1 // start: 触摸开始 2 start_fn (e) { 3 let self = this; 4 let touch_down = e.touches[0].clientY; 5 this.data.touch_down = touch_down; 6 // 获取 inner-wrap 的高度 7 wx.createSelectorQuery().select('#inner-wrap').boundingClientRect(function (rect) { 8 self.data.inner_height = rect.height; 9 }).exec(); 10 11 // 获取 scroll-wrap 的高度和当前的 scrollTop 位置 12 wx.createSelectorQuery().select('#scroll-wrap').fields({ 13 scrollOffset: true, 14 size: true 15 }, function (rect) { 16 self.data.start_scroll = rect.scrollTop; 17 self.data.height = rect.height; 18 }).exec(); 19 } 20 // end: 触摸开始
bindtouchend ---- end_fn:spa
1 // start: 触摸结束 2 end_fn (e) { 3 let current_y = e.changedTouches[0].clientY; 4 let self = this; 5 let { start_scroll, inner_height, height, touch_down } = this.data; 6 /** 7 * 一、下拉刷新 8 * 二、上拉加载 9 */ 10 if (current_y > touch_down && current_y - touch_down > 20 && start_scroll == 0) { 11 // 下拉刷新 的请求和逻辑处理等 12 } else if (current_y < touch_down && touch_down - current_y >= 20 && inner_height - height == start_scroll) { 13 // 上拉加载 的请求和逻辑处理等 14 } 15 } 16 // end: 触摸结束
原理就是触摸的时候,检查是否在顶部或者是底部,若是在顶部,还进行下拉,就进行刷新;若是在底部了,还进行上拉,就进行加载。使用 touchstart 和 touchend 的问题是用户必需要手指离开才会触发到。若是想要在顶部下拉就刷新,能够在 touchmove 中进行判断。
须要注意的是,使用上面的方法,会使 scroll-view 上 绑定 bindscroll 、bindscrolltopupper 和 bindscrolltoploweper 等方法是无效的。
样式和动画效果的优化,本身去进行吧。
若是有更好的方法,能够在评论下,留下你的方法供你们学习。
这一篇的方法只适合安卓机的,但仍是保留下来。