知識
不管是網(wǎng)站,軟件還是小程序,都要直接或間接能為您產(chǎn)生價值,我們在追求其視覺表現(xiàn)的同時,更側(cè)重于功能的便捷,營銷的便利,運營的高效,讓網(wǎng)站成為營銷工具,讓軟件能切實提升企業(yè)內(nèi)部管理水平和效率。優(yōu)秀的程序為后期升級提供便捷的支持!
您當(dāng)前位置>首頁 » 新聞資訊 » 小程序相關(guān) >
小程序自定義下拉刷新組件(為應(yīng)對頭部有非滾動區(qū)的情況) ...
發(fā)表時間:2021-2-20
發(fā)布人:葵宇科技
瀏覽次數(shù):88
效果動圖:
小程序是有其下拉刷新api的,然而頭部或者尾部有非滾動區(qū)域的情況下,是應(yīng)對不了的,相關(guān)問題在微信開放社區(qū)已經(jīng)是老生常談了,比如:
onPullDownRefresh 下拉刷新在安卓手機(jī)上會帶動頭部fixed元素一起下拉的問題
又比如:
小程序下拉刷新onPullDownRefresh 問題,fixed定位下移!
像這種問題有很多,不一一列舉了。
這個問題從2018年開始就不斷有開發(fā)者向微信開放社區(qū)反饋,一直到現(xiàn)在,都沒有解決,沒辦法,本公司項目中有頭部是固定非滾動的列表頁面,只得自己自定義一個。
列表頁的上拉加載,參考了這篇文章中的方法,鏈接放在這里,大家可以移步去看一下:
淺談微信小程序中的下拉刷新和上拉加載
回到主題,下拉刷新,我的思路是在這篇文章里找到的:
小程序開發(fā)踩坑記錄(五)——模擬實現(xiàn)底部tabbar和下拉刷新功能(解決安卓端打開下拉刷新功能后fixed元素失效問題)
我一上來打算用該文章中的方法,來自制下拉刷新,可是我是在自定義組件中使用,不是在page中定義,在自定義組件中scroll-view的onscroll事件怎么也響應(yīng)不了,也就無法獲得當(dāng)前頁面的scrollTop。
后來我受這個啟發(fā),既然可以在tocuh事件中改變scroll-view的scrollTop,來模擬出一個下拉刷新區(qū)域的scrollTop隨手指滑動而變化,進(jìn)而實現(xiàn)其下拉顯示和回彈,那我也可以使用絕對定位和相對定位,依靠改變?nèi)萜鞯膖op值來實現(xiàn)這個功能,也就是可以將滾動容器的top初始值設(shè)置為負(fù)的刷新區(qū)域的高度,在tocuhstart和tocuhmove事件中獲取手指在屏幕上的滑動距離,讓容器的top和滑動距離呈正相關(guān),當(dāng)top值達(dá)到自己設(shè)置的閾值的時候停止變化,隨后在tocuhend事件中發(fā)起刷新請求。
大體思路如上圖所示
下面貼一下基本代碼:
<view
class="scroll"
scroll-y
style="min-height: {{pageHeight + 'px'}}; top: {{marginTop + 'rpx'}}"
enable-back-to-top="{{true}}"
bindtouchmove="movePull"
bindtouchstart="startPull"
bindtouchend="endPull"
bindscroll="onScroll" >
<view class="scroll__content {{springbacking ? 'return__content' : ''}}" style="min-height: {{contentHeight + 'px'}};top: {{scrollTop + 'px'}}">
<view class="refresh__wrap">
<view class="refresh__center">
<view class="refresh__icon {{refreshText === '松開刷新' ? 'rotate' : ''}}" >
<mp-icon icon="sending" color="#999" size="{{35}}"></mp-icon>
</view>
<view class="tips">{{refreshText}}</view>
<view class="times">最后更新:{{refreshTime}}</view>
</view>
</view>
<slot />
<view class="footer__line" wx:if="{{recycleList.length}}">
<view class="scroll__loading" wx:if="{{bottomLoadingShow}}"></view>
<text class="text {{bottomLoadingShow ? 'notline' : ''}}">{{lineText}}</text>
</view>
</view>
<no-data
show="{{notDataShow}}"
bind:refresh="refresh" />
</view>
重點說下,這個組件結(jié)構(gòu)為外層.scroll元素,最小高度設(shè)置為pageHeight(計算方法后面會貼),position為relative,其top值設(shè)置為父級頁面?zhèn)魅氲膍arginTop值,就是父級頁面頭部非滾動元素的rpx高度,如果沒有非滾動元素,則默認(rèn)為0,這樣的話,外層的位置就可以依賴marginTop值來確定了,滾動的時候不會把非滾動區(qū)域也算進(jìn)去;
內(nèi)層列表滾動區(qū)域.scroll__content元素,position為absolute最小高度contentHeight,top值scrollTop,初始-80px(刷新文案元素高度),這樣就把.refresh__wrap刷新文案元素隱藏起來了。此外,設(shè)置一個默認(rèn)插槽,就是列表循環(huán)內(nèi)容。
pageHeight和contentHeight計算方法,用到wx.getSystemInfozhege api,比較簡單:
getPageHeight() {
const self = this;
wx.getSystemInfo({
success: (res) => {
self.setData({
pageHeight: res.windowHeight - (self.data.marginTop / 750 * res.windowWidth),
contentHeight: (res.windowHeight - (self.data.marginTop / 750 * res.windowWidth)) + REFRESHHEIGHT + 2,
})
}
})
}
以上,marginTop是父級組件傳進(jìn)來的頭部非滾動區(qū)域的rpx高度值(頭部非滾動區(qū)域position設(shè)置為fixed),默認(rèn)為0,REFRESHHEIGHT是80,就是刷新文案區(qū)域的高度px值,最后加2是保證在第一頁鋪不滿整屏的情況下,能讓onReachBottom上拉事件生效,上拉加載本文不多說了,可以直接去看上面貼出的鏈接:“淺談微信小程序中的下拉刷新和上拉加載”(注意,我這里是自定義組件,onReachBottom事件同樣要在父頁面中寫onReachBottom生命周期,來調(diào)用自定義組件中的onReachBottom方法)。
tocuhstart方法,就是獲取手指開始接觸屏幕的clentY值:
startPull(ev) {
this.lastTop = ev.changedTouches[0].clientY;
},
Tocuhmove方法:
// MAX_MOVE_TOP 為 120 允許最大滑動距離
// MAX_SCROLL_TOP 為 20 允許.scroll__content的最大top值
movePull(ev) {
this.nowY = ev.changedTouches[0].clientY;// 手指當(dāng)前觸摸位置的clentY值
this.nowY = this.nowY - this.lastTop;// 滑動距離
const query = wx.createSelectorQuery();
query.select('.scroll').boundingClientRect();
query.selectViewport().scrollOffset();
query.exec((rect) => { // 必須是滾動高度為0即在頂部的時候觸發(fā)
if (rect[1].scrollTop <= 0 && this.nowY > 0 && this.nowY <= MAX_MOVE_TOP && this.data.recycleList.length) {
this.setData({// 滿足以上條件的,則使.scroll__content元素的top值等于-80px 加上滑動距離 nowY
scrollTop: -REFRESHHEIGHT + this.nowY,
})
if(this.nowY >= 100) {
this.setData({
refreshText: '松開刷新',
})
}
}
})
if(this.nowY > MAX_MOVE_TOP && this.data.scrollTop < MAX_SCROLL_TOP) {
this.setData({// 此處判斷是為了解決手指滑動過快,tocuhmove得到的clentY值呈非線性變化,導(dǎo)致滑動距離可能上一次還是100以內(nèi),下一次直接就到300開外,無法滿足上面的top變化條件,就卡住了。所以此時手動將.scroll__content的top值設(shè)置為20。
refreshText: '松開刷新',
scrollTop: MAX_SCROLL_TOP,
})
}
...
// 上拉加載邏輯
...
}
Tocuhend事件:
endPull() {// 結(jié)束滑動的時候當(dāng).scroll__content的top值大于等于20,則可以執(zhí)行刷新方法。
if(this.data.scrollTop >= MAX_SCROLL_TOP) {
wx.showNavigationBarLoading();
this.refresh();
}
...
// 上拉加載邏輯
...
if (this.data.scrollTop > -REFRESHHEIGHT) {
this.setData({ // 這個springbacking為true的時候,.scroll__content元素的transition就是0.4s,回彈時候的動畫效果。
springbacking: true,
scrollTop: -REFRESHHEIGHT
})
}
},
好了,下拉刷新的邏輯就寫完了,該下拉刷新在安卓和ios上的效果差別不是很大,由于業(yè)務(wù)需要,我是把他做成了一個組件,一些刷新方法和父頁面的請求事件成功交互,失敗交互,不在本文探討范圍之內(nèi),所以就略去了,想試試的朋友可以直接在頁面中將slot插槽替換成列表循環(huán)元素嘗試。
相關(guān)案例查看更多
相關(guān)閱讀
- 云南衛(wèi)視小程序
- 百度自然排名
- 小程序分銷商城
- 云南網(wǎng)站建設(shè)哪家好
- 旅游網(wǎng)站建設(shè)
- 江蘇小程序開發(fā)
- 云南網(wǎng)站建設(shè)百度
- 小程序技術(shù)
- 網(wǎng)站制作
- 網(wǎng)站建設(shè)公司地址
- 云南企業(yè)網(wǎng)站
- 紅河小程序開發(fā)
- 報廢車拆解系統(tǒng)
- 汽車回收管理
- 云南網(wǎng)站建設(shè)費用
- vue開發(fā)小程序
- 前端技術(shù)
- 商標(biāo)注冊
- 云南做軟件
- .net網(wǎng)站
- 前端開發(fā)
- 網(wǎng)站建設(shè)電話
- 云南網(wǎng)站建設(shè)首選公司
- 小程序定制
- 報廢車拆解管理系統(tǒng)
- Web開發(fā)框架
- 云南小程序開發(fā)費用
- 開發(fā)制作小程序
- 云南微信小程序開發(fā)
- 商標(biāo)