Vor kurzem arbeite ich an einem
Live-Broadcast-Modul
desWeChat Mini-Programms
. Die Chatroom-Funktion im Modul verwendetscroll-view + one-. dimensionales Array
Es wird in Form von Code> angezeigt und es wurde keine Optimierung durchgeführt, was zu einer schlechten Benutzererfahrung führt微信小程序
的直播模块
,模块里的聊天室功能是用scroll-view + 一维数组
的形式展示的,而且也没有进行任何的优化,导致用户的体验感比较差
首先模拟一下优化前的聊天室
情况
肉眼可见的蛋疼~
但是优化还是得优化滴,不优化是不可能滴,但是在开始之前,我觉得有必要把优化步骤拆分为以下两点?
1. 不再使用
scroll-into-view
设置锚点由于旧版本使用的是
scroll-view + 一维数组
的形式实现的,这就导致在数据添加后页面总会显示加载后的最后一条信息
,而不是加载前的最后一条信息
,因此上一任开发者使用了scroll-into-view
属性作为数据加载后的回位锚点
,但是由于锚点指向
的切换和数据加载
并不是同步发生的,这就导致出现回弹
的现象
2. 大量数据的处理
因为是
聊天室
功能,因此不可避免的需要加载大量的用户对话、图片等内容,又因为scroll-view
本身并不适合加载大量的数据(太菜了想不出来其他办法),故而需要在数据的加载和显示部分下点功夫处理一下
3. 附加功能处理
聊天室原本还有
返回底部
等功能存在,因此在完成优化后原本的功能也不能忽略
OK开工~
为什么要倒置scroll-view
呢?从上面的第一点我们可以看出,如果需要正序地插入数据,那么就会不可避免地出现数据加载后无法显示后面数据
的情况,但是想要解决这种情况又需要使用scroll-into-view
属性,那么如果需要彻底地解决这个问题,就需要从问题的根源scroll-view
下手
首先是修改前
的代码?
<view>这是一个直播画面</view> <scroll-view> <view> {{ item.data }} </view> </scroll-view>
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); };
那么就先来试一下倒置scroll-view
到底也没有效果
首先我们需要给scroll-view
套上一个transform:rotate(180deg)
的属性,然后再给内部的子元素也套上同样的属性,别忘了给存放数据的数组
也倒置一下,最重要的,把scroll-view
上的scroll-into-view
属性去掉,就会得到这样的效果?
还有就是此时滚动条
的位置是在左边的,如果有需要可以使用CSS
属性去掉,或者自行模拟,下面是去去除滚动条的CSS样式
?
::-webkit-scrollbar { display:none; width:0; height:0; color:transparent; }
到这里还只是第一步
,下一步是如何下拉加载数据
。
此时我们的scroll-view
是处于倒置
的状态,也就是说顶部是底,底部才是顶
(搁着绕口令呢),所以之前使用的scrolltoupper触顶方法
要替换成scrolltolower触底方法
才能实现“下拉加载”
下面是目前的聊天室
Chatroom
-Situation zuvor Optimierung🎜 Sichtbarer Ei-Schmerz~🎜 🎜Ohne Optimierung geht es aber nicht. Aber bevor ich anfange, ist es meiner Meinung nach notwendig, die Optimierungsschritte in die folgenden zwei Punkte aufzuteilen?🎜🎜🎜Nicht mehr mit scroll-in-view
Ankerpunkt setzen🎜🎜Da die alte Version in Form von scroll-view + eindimensionales Array
implementiert wurde, ergab sich dies Die Seite ist immer voll, nachdem die Daten hinzugefügt wurden. Es wird Die letzte Nachricht nach dem Laden
anstelle von Die letzte Nachricht vor dem Laden
angezeigt, sodass der vorherige Entwickler verwendet hat scroll-into-view
>Das Attribut dient als Rückgabeankerpunkt
, nachdem die Daten geladen wurden. Da jedoch der Ankerpunkt
und der Daten erfolgt nicht gleichzeitig. Dies führt zum Bounce
-Phänomen🎜🎜🎜Verarbeitung großer Datenmengen🎜🎜 Da es sich um eine Chatroom
-Funktion handelt, ist es unvermeidlich, eine große Menge an Benutzerkonversationen, Bildern und anderen Inhalten zu laden, und weil scroll-view
selbst nicht dafür geeignet ist Laden einer großen Datenmenge (es ist zu schade, an andere Methoden zu denken), daher muss am Lade- und Anzeigeteil gearbeitet werden🎜🎜🎜Zusätzliche Funktionsverarbeitung🎜🎜Der Chatroom verfügte ursprünglich über Funktionen wie Zurück nach unten
, daher können die ursprünglichen Funktionen nach Abschluss der Optimierung nicht ignoriert werden🎜🎜OK, um zu beginnen~🎜 scrollen umkehren? Was ist mit der Ansicht
? Aus dem ersten Punkt oben können wir ersehen, dass, wenn Daten in positiver Reihenfolge eingefügt werden müssen, es zwangsläufig zu einer Situation kommt, in der die nachfolgenden Daten nach dem Laden der Daten nicht angezeigt werden können
, aber wir wollen Um diese Situation zu lösen, müssen Sie das Attribut scroll-into-view
verwenden. Wenn Sie dieses Problem also vollständig lösen müssen, müssen Sie an der Wurzel des Problems scroll-view beginnen
🎜🎜Zuerst Code vor dem Ändern
?🎜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 <pre class="brush:php;toolbar:false"><scroll-view> <view> <view> {{ item.data }} </view> </view> </scroll-view>
die Scroll-Ansicht umzukehren
, aber es hat keine Auswirkung🎜🎜Zuerst müssen wir es tun Legen Sie scroll-view
das Attribut des vorherigen transform:rotate(180deg)
fest und wenden Sie dann dasselbe Attribut auf die internen untergeordneten Elemente an. Vergessen Sie nicht, das array, das auch die Daten speichert, das Wichtigste ist, das Attribut scroll-into-view
aus scroll-view
zu entfernen, und Sie werden es tun Erhalten Sie diesen Effekt? >🎜🎜Es gibt auch die Bildlaufleiste<. die position von> befindet sich auf der linken Seite. Bei Bedarf können Sie sie mit dem <code>CSS
-Attribut entfernen oder selbst simulieren Ist der CSS-Stil zum Entfernen der Bildlaufleiste
? 🎜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(); };
erste Schritt
. Der nächste Schritt ist wie man Daten herunterzieht und lädt
Code>. 🎜🎜Zu diesem Zeitpunkt befindet sich unsere Bildlaufansicht
in einem invertierten
-Zustand, was bedeutet, dass die Oberseite unten und die Unterseite die Oberseite
ist > (lassen Sie es beiseite Zungenbrecher), daher muss die zuvor verwendete scrolltoupper top-Methode
durch scrolltolower bottom-Methode
ersetzt werden, um ein „Pull-Down-Laden“ zu erreichen🎜🎜🎜🎜Das Folgende ist der aktuelle Chatroom
Sieht viel besser aus🎜🎜🎜🎜回弹问题
后,就需要考虑如何处理大量数据
。由于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教程》
Das obige ist der detaillierte Inhalt vonLassen Sie uns über das Dropdown-Laden der Scroll-Ansicht in Uniapp sprechen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!