最近、
WeChat アプレット
のライブ ブロードキャスト モジュール
に取り組んでいます。モジュールのチャット ルーム機能は次を使用しています。scroll -view は 1 次元配列の形式で表示されます
、最適化が実行されていないため、ユーザー エクスペリエンスが低下します
最初に をシミュレートしますチャット ルーム## 最適化前 # 状況
1. アンカーの設定に scroll-into-view
古いバージョンはを使用しなくなりましたpoint
スクロールビュー 1 次元配列
の形式で実装されているため、ページには常に
の最後の情報が表示されます。データ追加後のロードであり、ロード前の最後の情報
ではないため、前の開発者はscroll-into-view
属性をとして使用しました。データロード後にアンカーポイント
を返しますが、スイッチングを指す
アンカーポイントとデータロード
は同時に発生しないため、リバウンド現象が発生します。
2. 大量のデータの処理チャット ルーム
機能であるため、ユーザーの会話や画像などのコンテンツを大量に読み込むことは避けられず、
scroll-view
自体が大量のデータを読み込むのには適していないため (他の方法を考えるのは残念です)、データの読み込みと表示に力を入れる必要があります
3. 追加機能処理なぜ##チャット ルームには元々 ## がありました#一番下に戻る と他の関数があるため、最適化が完了した後は元の関数を無視することはできません
##OK 開始します~
1. スクロール ビューを反転します
scroll-view
を反転する必要があるのでしょうか?上記の最初の点から、データを正の順序で挿入する必要がある場合、必然的にscroll-into-view 属性を使用する必要があります。この問題を完全に解決する必要がある場合は、問題の根本である
scroll-view## から始める必要があります。 #まずは
修正前の
のコード?<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false"><view>这是一个直播画面</view>
<scroll-view>
<view>
{{ item.data }}
</view>
</scroll-view></pre><div class="contentsignin">ログイン後にコピー</div></div>
<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">const scrollIntoView = ref("index1");
const upper = () => {
let lastNum = scrollData.value[0].data;
let newArr = [];
for (let index = 1; index {
scrollIntoView.value = `index${lastNum}`;
console.log("scrollIntoView :>>", scrollIntoView.value);
}, 100);
};
const getRandomColor = () => {
return "#" + Math.random().toString(16).substr(2, 6);
};</pre><div class="contentsignin">ログイン後にコピー</div></div>
じゃあ、まずは試してみましょう
endまず、
Apply a transform:rotate(180deg)
属性を指定し、次に同じ属性を内部の子要素に適用する必要があります。
scroll-view の
scroll-into-view 属性を削除することです。この効果は得られますか?
また、この時点では、
スクロール バー
の位置は左側にあります。必要に応じて、
属性を使用して削除するか、自分でシミュレートします。次の手順は スクロール バーの CSS スタイルを削除する
?::-webkit-scrollbar { display:none; width:0; height:0; color:transparent; }
これは単なる
です。最初のステップ、次のステップは
データをプルダウンしてロードする方法です。
現時点では、スクロールビューは
反転状態です。つまり、
上が下で、下が上です。
scrolltoupper top メソッド を
scrollto lowerbottom メソッド に置き換える必要があります
現在の チャット ルーム
見た目はかなり良くなりました
回弹问题
后,就需要考虑如何处理大量数据
。由于uni-app
官方也在文档中提到scroll-view
加载大批量数据的时候性能较差,但无奈手头上也没有别的办法,只能死马当活马医了我第一个想法就是非常经典的虚拟列表
,但是此前所看的很多关于虚拟列表的文章都是在web端
实现的,似乎小程序领域里并不是一个被经常采用的方法,但是所幸还是找到了如何在微信小程序实现虚拟列表
的资料,详情可以查看这篇文章?微信小程序虚拟列表
OK说干就干,那么第一步就是要明确实现虚拟列表需要什么样的数据结构
,虚拟列表其实简单地说就是当某一个模块的数据超出了可视范围就将其隐藏
,那么如何将数据分为多个模块呢?答案就是二维数组
首先将当前的页码
存储起来(默认为0),当触发下拉加载动作时页码+1
,然后以当前页码作为下标
存入数组
const currentShowPage=ref(0) const upper = () => { let len = scrollData.value[currentShowPage.value].length - 1; let lastNum = scrollData.value[currentShowPage.value][len].data; let newArr = []; currentShowPage.value += 1; for (let index = 1; index <p>当然别忘了在页面中也需要以<code>二维数组</code>的形式循环数据</p><pre class="brush:php;toolbar:false"><scroll-view> <view> <view> {{ item.data }} </view> </view> </scroll-view>
数据结构
的问题解决了,那么接下来就是如何判断数据模块是否超出可视范围
。首先我们需要知道每个数据模块的高度
,其实很简单,只需要为每个模块定义一个id
,然后在数据展示之后根据id
获取到该模块的节点信息
然后按顺序存储到数组中
即可
const pagesHeight = [] onReady(()=>{ setPageHeight() }) const upper = () => { ... nextTick(() => { // 每次获取新数据都调用一下 setPageHeight(); }); }; const setPageHeight = () => { let query = uni.createSelectorQuery(); query .select(`#item-${currentShowPage.value}`) .boundingClientRect(res => { pagesHeight[currentShowPage.value] = res && res.height; }) .exec(); };
OK,现在我们已经知道每个模块的高度
了,然后就是监听模块与可视窗口的交叉范围
。这里有两种方法,一种是JS获取可视窗口的高度与模块scrollTop进行差值计算
,另一种是使用小程序的createIntersectionObserver方法让程序自行监听交叉区域
这里我展示的是第二种方法,如果对第一种方法感兴趣的朋友可以向上看第二章开头我推荐的《微信小程序虚拟列表》文章
关于createIntersectionObserver方法
的使用其实很简单,我们只需要把可视窗口的id
以及需要监听的模块id
传入即可,详情看官方文档
onReady(() => { ... observer(currentShowPage.value); }); const upper = () => { ... nextTick(() => { // 每次获取新数据都调用一下 observer(); }); }; // 允许渲染的数组下标,需要设置默认值 const visiblePagesList = ref([-1,0,1]) const observer = pageNum => { const observeView = wx .createIntersectionObserver() .relativeTo("#scroll", { top: 0, bottom: 0 }); observeView.observe(`#item-${pageNum}`, res => { if (res.intersectionRatio > 0) visiblePagesList.value = [pageNum - 1, pageNum, pageNum + 1]; }); };
最后就是在页面中判断该模块是否允许被渲染(也就是是否存储在visiblePagesList数组中)
,这里就很简单了,只需要写一个方法在页面中调用即可
<scroll-view> <view> <template> <view> {{ item.data }} </view> </template> <view></view> </view> </scroll-view>
const includePage = index => { return visiblePagesList.value.indexOf(index) > -1; };
来看看效果如何
额...似乎没有太大区别,那我们看看页面结构到底也没有将可视区域外的内容切换为空白view
成功!
聊天室原本还有回底功能
等,也不能忘了加上
这个部分就比较简单了,只需要直接使用scroll-view
的scroll-top属性
,然后通过在scroll回调中动态记载scroll-top的值即可
下面是部分代码
<scroll-view> ... </scroll-view> <view>回底</view>
let scrollTop; const currentTop = ref(0); const showGoBottom = ref(false); const handle_scroll = throttle(event => { scrollTop = event[0].detail.scrollTop; if (scrollTop > 300) { showGoBottom.value = true; } }, 100); const handle_goBottom = () => { currentTop.value = scrollTop; nextTick(() => { currentTop.value = 0; }); showGoBottom.value = false; };
大功告成~
最后附上demo仓库
https://gitee.com/huang-qihao123/virtual-list-demo
推荐:《uniapp教程》
以上がuniapp のスクロールビュー ドロップダウンの読み込みについて話しましょうの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。