プルダウンリフレッシュとプルアップロードは、非常に一般的なビジネス要件です。WeChatアプレットでは、プルダウンリフレッシュメソッドが提供されていonPullDownRefresh
ます。プルアップローディングを実装することは比較的不便です。
プルダウンして更新
公式のWeChatドキュメントには多くの落とし穴がありますが、プルダウンリフレッシュの導入は依然として非常に包括的です。少しここに持ってきました。
- まず、グローバル
config
でwindow
の構成enablePullDownRefresh
。 - で
Page
定義onPullDownRefresh
フック関数。プルダウンリフレッシュ条件に達した後、フック関数が実行され、リクエストメソッドが開始されます。 - リクエストが戻った後、
wx.stopPullDownRefresh
プルダウンの更新を停止するために呼び出します。
設定
config = {
pages: [
'pages/index'
],
window: {
backgroundTextStyle: 'light',
navigationBarBackgroundColor: '#ccc',
navigationBarTitleText: 'WeChat',
navigationBarTextStyle: '#000',
enablePullDownRefresh: true
}
}复制代码
ページ
onPullDownRefresh() {
wepy.showNavigationBarLoading()
setTimeout(()=>{
this.getData = '数据拿到了'
wepy.stopPullDownRefresh()
wepy.hideNavigationBarLoading()
this.$apply()
},3000)
}复制代码
効果は次のとおりです。プルダウンプロセスが少し難しいことがわかります。これが実際に背景色が追加されない理由です。背景色を追加してから再試行してください。気分が良くなりました。プルダウンリフレッシュには、実装が簡単な既製の構成と方法がありますが、プルアップのロードは異なります。
ローディングを引き上げる
達成される効果を最初に見てください。これは3g側のプルアップローディングです。アプレットは同じ効果を達成する必要があります。まず第一に、機能は
- トップに戻るをクリックすると、これは非常によく実装されており、対応するトップに戻る機能があります
- 画面をスライドして現在のページ番号を記録することも非常に簡単です。主に、スクロールイベントを監視し、対応するスクロールバーの高さを決定し、スクロールバーと子コンテナの高さを計算します。
- 読み込みアニメーションをプルアップ
ここには2つの実装スキームがあります。1つは、page
組み込みのプルダウンボトムフックイベントonReachBottom
で、最後に時間の一部をプルダウンして、ボトムをヒットしたことを通知することですscroll-view
。これは、イベントに付属のラベルです。次に、2つの方法を使用してプルアップロードを実装します。
ReachBottomでボトムイベントをプルアップ
テンプレート
<template>
<view class="loading"></view>
<view class="container"
@touchmove="moveFn"
@touchstart="startFn"
@touchend="endFn"
style="transform:translate3d(0,{
{childTop}}px,0)">
<repeat for="{
{list}}"
key="index"
index="index"
item="item">
<view>{
{ item }}<text>{
{index}}</text></view>
</repeat>
</view>
</template>复制代码
フック機能
data = {
getData: '',
top: 0,
lastTop: 0,
canDrag: false,
list: []
}
onReachBottom() {
this.canDrag = true
}
methods = {
moveFn(ev) {
let nowY = ev.changedTouches[0].clientY
nowY = nowY-this.lastTop
if(nowY > 0 )
this.canDrag = false
if( nowY<=0 && this.canDrag ) {
this.top = nowY
}
if( -this.top>= this.maxTop )
this.top = -this.maxTop
},
startFn(ev) {
this.lastTop = ev.changedTouches[0].clientY
},
endFn() {
if(this.top <= -this.maxTop) {
this.text = "去请求数据了"
setTimeout(()=>{
this.text = "请求回来了"
this.canDrag = false
this.list.push(...["数据","数据","数据"])
this.$apply()
this.top = 0;
return
},1000)
}
},
gotoTop() {
wepy.pageScrollTo({
scrollTop: 0
})
}
}复制代码
プルアップローディングを実現するためのローリングコンテナ
scroll-view:スクロール可能なビュー領域。
その特定の使用法は詳細には触れません。公式文書を見てください。上記の問題の解決策は次のとおりです。
bindscrolltolower
ネイティブアナロジーグローバルフックonReachBottom
テンプレート
<scroll-view scroll-y
id="content"
@scroll="scroll"
@scrolltolower="lower"
scroll-top="{
{gotoTopNum}}"
lower-threshold="100"
style="transform:translate3d(0,{
{childTop}}px,0)">
<view class="sty-search"
@touchmove="moveContent"
@touchstart="startContent"
@touchend="endContent">...</view>
</scroll-view>复制代码
上記は最終的なテンプレートですが、なぜこれほど複雑なのか疑問に思われるかもしれません。複雑ですが、それぞれの属性は便利です。もちろん、私たちを待っているいくつかの落とし穴があります。
まず、ノードはローリングコンテナとサブコンテナに分割されます。
Q:スクロールコンテナにネストされたサブコンテナがあり、3つのドラッグメソッドがそれにバインドされているのはなぜですか?
A:scroll-view
コンテナはtouchmove
イベントをバインドできないため、これが最初のピットです。バインドするとどうなりますか?それほど多くはありませんが、イベントフックは呼び出されません。(このピットは公式ドキュメントにはありません。当時、バインドされていて呼び出されていませんでした。コミュニティで、touchmoveイベントをサブコンテナにバインドするという解決策が見つかりました)
コードを見てみましょう。
methods = {
async lower() {
this.canDrag = true
},
scroll (ev) {
this.scrollTop = ev.detail.scrollTop
if (ev.detail.deltaY > 0) {
this.canDrag = false
}
let nowSet = this.documentHeight+this.scrollTop-this.contentHeader
let num = Math.ceil(nowSet/this.listHeight) - 1
num = Math.floor(num / this.pageBean.pageSize) + 1
num = (num > this.pageBean.pageNo) ? this.pageBean.pageNo : num
if(num != this.page) {
this.page = num
this.$apply()
}
},
startContent(ev) {
this.lastTop = ev.changedTouches[0].clientY
if(!this.documentHeight){
this.documentHeight = wx.getSystemInfoSync().windowHeight
}
/* 这句是解决回到顶部的bug */
if (this.gotoTopNum || this.gotoTopNum==0) { this.gotoTopNum = undefined }
},
moveContent (ev) {
let {
pageNo,
pageSize,
totalCount
} = this.pageBean
let nowY = ev.changedTouches[0].clientY
nowY = nowY-this.lastTop
if (this.canDrag && nowY) {
this.state = 1;
if (nowY <= -this.maxMove) {
nowY = -this.maxMove
}
if (nowY <= 0) {
this.childTop = nowY
}
}
},
async endContent(ev) {
let {
pageNo,
pageSize,
totalCount
} = this.pageBean
if (this.childTop === -this.maxMove) {
/* 状态 */
if (pageNo >= this.maxPage || pageNo * pageSize >= totalCount) {
this.state = 0
} else {
this.pageBean.pageNo++
await this.fillData()
this.childTop = 0
this.canDrag = false
this.$apply()
}
}
/* 如果没超过刷新高度则重置 */
this.childTop = 0
},
gotoTop() {
this.gotoTopNum = 0
},
}
复制代码
Q:なぜtouchStart
時間をgotoTopNum
設定する必要があるのundefined
ですか?
A:このページの先頭に戻る機能があるため、先頭に戻るとgotoTopNum
、実際にはscrollTop
変更されますが、次のターンは0に設定されますが、0に設定されgotoTopNum
ます。もう一度上に戻ると、データが変更されていないため、ビューレイヤーは更新されません。したがって、無効な値がtouchStart
指定されgotoTopNum
た場合は、もう一度クリックして一番上に戻ると、ビューレイヤーも更新されます。
ネイティブスクロールまたはスクロールビュー
比較 | ネイティブスクロール | スクロールビュー |
---|---|---|
パフォーマンス | スムーズ | ノードが多すぎると明らかにフリーズします |
ローリング機能 | onPageScroll | bindscroll |
トップに戻る | wepy.pageScrollTo(object)にはデフォルトでアニメーション効果があり、キャンセルすることはできません | ノードプロパティを設定する scroll-top |
ピット | まだ見つかりません | 1、およびenablePullDownRefresh 、ReachBottom は共存できません2、touchmoveイベント3をバインドできません、バーをダブルクリックしてトップの「イースターエッグ」に戻ることはできません |
終了...あなたは...
どういたしまして。
実機試験
実装されたプルアップロードはエミュレータ上でスムーズに実行され、問題はありません。だが。
Macマシンの場合(当面はiphone5とiPhone7でテスト中)、プルアップまたはプルダウンのリバウンド効果などの問題があり、この効果はプルアップの距離に影響します。
この問題は古くから考えられてきましたが、今のところ上品に解決することはできません。
そこで、プロダクトマネージャーに要件を変更してもらい、プルアップアニメーション効果を削除して、最終的な効果が次のようになるようにしました。
総括する
- バージョン1.4.0のリリース後、WeChatアプレットのノードの操作は高価であり、ブラウザーでの操作よりも高価です(これは、3g側のプルアップロード機能とWeChatアプレットの滑らかさを比較することで得られます)。多くのメソッドには、幅と高さを
id
取得するノード、またはノードセレクターを取得するノードなどの操作ノードが与えられます。これらのメソッドを呼び出す頻度を最小限に抑える函数节流
か()、結果をキャッシュしてください - あなたがそれをする前にあなたの脳を使ってください!!!そうでなければ、あなたは多くの回り道をするでしょう...