在小程序中onLoad生命鉤子只在頁面建立時調用一次,在作navigateTo頁面跳轉後,返回上級頁面,因爲navigateTo跳轉只是隱藏了當前頁面,所以返回上一級頁面時onLoad生命鉤子不會再次執行,這樣帶來的好處是頁面能快速展現出來,可是onLoad中的請求數據不會實時更新,這時候就須要一個下拉刷新的操做來幫助用手動更新頁面數據,接下來這篇文章將會介紹小程序中實現下拉刷新的三種方式css
enablePullDownRefresh是最容易實現下拉刷新的方法,在json文件中將enablePullDownRefresh設置爲true,在Page中監聽onPullDownRefresh事件便可,支持點擊頂部標題欄回到頂部,自定義標題欄時會失效,還能夠經過直接調用wx.startPullDownRefresh()觸發下拉刷新事件,產生下拉刷新動畫,處理完下拉刷新中的數據更新後調用wx.stopPullDownRefresh()結束動畫便可。
這種形式的下拉刷新的優勢很明顯就是簡單,沒有限制,可是缺點也一樣明顯:html
scroll-view是官方的一個滾動視圖組件,使用很簡單,想要設置上拉刷新代碼以下:json
<scroll-view class="scroll" scroll-y bindscrolltoupper="refresh">
<view class="content">content</view>
</scroll-view>
複製代碼
想要利用scroll-view實現上拉刷新,須要注意:小程序
scroll-view缺點:xss
scroll-view優勢:ide
官方並不推薦使用scroll-view作下拉刷新,官方文檔上有這樣一個tip: 測試
自定義下拉刷新最主要但願解決的問題仍是在Android使用enablePullDownRefresh時fixed定位的標題欄或導航欄會被下拉的問題,同時兩端在下拉刷新時的動畫保持一致,其實實現起來並不難,接下來就看看具體實現:
wxml:flex
<view class="scroll" bindtouchstart="touchStart" bindtouchmove="touchMove" bindtouchend="touchEnd">
<view class="animation">
<view class="loading"></view>
<text class="tip">{{state === 0 ? '下拉刷新' : state === 1? '鬆開刷新' : '刷新中'}}</text>
</view>
<view style="transform: translateY({{translateHeight}}rpx)">
<slot name="content"></slot>
</view>
</view>
複製代碼
這個文件定義組件的模版,有一個滾動view包裹,綁定了touch事件,裏面包含下拉刷新時的動畫,和一個slot,slot用於插入滾動列表的內容
wxss:動畫
.animation {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 150rpx;
margin-bottom: -150rpx;
background-color: #fff;
}
.loading {
width: 30rpx;
height: 30rpx;
border:6rpx solid #333333;
border-bottom: #cccccc 6rpx solid;
border-radius: 50%;
animation:load 1.1s infinite linear;
}
@keyframes load{
from{
transform: rotate(0deg);
}
to{
transform: rotate(360deg);
}
}
.tip {
margin-left: 10rpx;
color: #666;
}
複製代碼
樣式文件這沒什麼特別的
js:ui
let lastY = 0 // 上一次滾動的位置
let scale = 750 / wx.getSystemInfoSync().windowWidth // rpx轉化比例
Component({
options: {
multipleSlots: true
},
data: {
scrollTop: 0,
translateHeight: 0, // 平移距離
state: -1
},
properties: {
// 觸發下拉刷新的距離
upperDistance: {
type: Number,
value: 150
}
},
methods: {
// 監聽滾動,獲取scrollTop
onPageScroll (e) {
this.data.scrollTop = e.scrollTop
},
touchStart (e) {
lastY = e.touches[0].clientY
},
touchMove (e) {
let clientY = e.touches[0].clientY
let offset = clientY - lastY
if (this.data.scrollTop > 0 || offset < 0) return
this.data.translateHeight += offset
this.data.state = 0
lastY = e.touches[0].clientY
if (this.data.translateHeight - this.data.scrollTop * scale > this.data.upperDistance) {
this.data.state = 1
}
this.setData({
translateHeight: this.data.translateHeight,
state: this.data.state
})
},
touchEnd (e) {
if (this.data.translateHeight - this.data.scrollTop * scale > this.data.upperDistance) {
this.setData({
translateHeight: 150
})
this.triggerEvent('scrolltoupper')
this.setData({
state: 2
})
} else if (this.data.scrollTop <= 0) {
this.stopRefresh()
}
},
// 中止刷新
stopRefresh () {
this.setData({
translateHeight: 0,
state: -1
}, () => {
wx.pageScrollTo({
scrollTop: 0,
duration: 0
})
})
}
}
})
複製代碼
這個下拉刷新組件最重要的是控制下拉刷新的時機,代碼體現就是定義了一個upperDistance,下拉刷新的距離來判斷是否執行刷新。手指滑動時,獲取滑動距離,translateHeight累加用於展現,在touchEnd事件中判斷滑動距離是否達到設定值,達到設定值就發送scrolltoupper事件,在父組件中監聽便可,不然中止刷新。
<header title="下拉刷新" background="#fff"></header>
<refresh-scroll id="refreshScroll" bindscrolltoupper="refresh">
<view class="item" slot="content" wx:for="{{list}}">{{item}}</view>
</refresh-scroll>
複製代碼
Page({
data: {
list: []
},
onLoad: function () {
this.refreshScroll = this.selectComponent('#refreshScroll')
for (let i = 0; i < 10; i++) {
this.data.list.push(i)
}
this.setData({
list: this.data.list
})
},
onPageScroll (e) {
this.refreshScroll.onPageScroll(e)
},
onReachBottom () {
wx.showLoading({
title: 'onReachBottom'
})
setTimeout(() => {
wx.hideLoading()
}, 1000)
},
refresh: function (e) {
setTimeout(() => {
this.refreshScroll.stopRefresh()
}, 1000)
}
})
複製代碼
在使用時關鍵是要將頁面中onPageScroll中獲取的值傳遞下去,而後bindscrolltoupper監聽scrolltoupper事件,執行刷新操做而後再調用stopRefresh中止刷新,下來看真機上的測試效果:
iOS:
本篇文章介紹了小程序下拉刷新時的三種方法,前兩種都是小程序官方提供的,最後一種是我的的思考總結,寫的也比較簡單,想要項目應用,還須要本身完善,只但願爲你們作自定義下拉刷新提供一個思路。 若是有錯誤或不嚴謹的地方,歡迎批評指正,若是喜歡,歡迎點贊