1、在微信小程式中,想到 下拉重新整理 和 上拉載入,如果是整個頁面都拖動的話,可以在頁面配置中,配置 enablePullDownRefresh 和 onReachBottomDistance 然後在 .js 中 使用 Page.onPullDownRefresh 和 Page.onReachButton 這樣來進行。
2、上面的做法是官方推薦我們做頁面的 下拉重新整理 和 上拉載入 所使用的方法。但某種情況比如頭部是固定的,但使用上面的方法,整個頁面都拉動,會顯得很奇怪。這個時候,我們的滾動實際上是使用了 scroll-view 來進行的,會顯得更加好看。
3、使用 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>
通常我們都寫法,都如上面一樣,但因為要拿到滾動的最大高度,所以需要寫成下面的樣式:
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:
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:
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 * 1、下拉重新整理 8 * 2、上拉載入 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 等方法是無效的。
樣式和動畫效果的優化,自己去進行吧。
如果有更好的方法,可以在評論下,留下你的方法供大家學習。
這一篇的方法只適合安卓機的,但還是保留下來。