ホームページ  >  記事  >  ウェブフロントエンド  >  uniapp のスクロールビュー ドロップダウンの読み込みについて話しましょう

uniapp のスクロールビュー ドロップダウンの読み込みについて話しましょう

青灯夜游
青灯夜游転載
2022-07-14 21:07:083676ブラウズ

uniapp のスクロールビュー ドロップダウンの読み込みについて話しましょう

最近、WeChat アプレット ライブ ブロードキャスト モジュール に取り組んでいます。モジュールのチャット ルーム機能は次を使用しています。 scroll -view は 1 次元配列の形式で表示されます 、最適化が実行されていないため、ユーザー エクスペリエンスが低下します

最初に をシミュレートしますチャット ルーム## 最適化前 # 状況

uniapp のスクロールビュー ドロップダウンの読み込みについて話しましょう

目に見える卵の痛み~

しかし、最適化は依然として最適化する必要があります。最適化しないことは不可能ですが、最適化する前にまず、最適化の手順を次の 2 つのポイントに分割する必要があると思いますか?

1. アンカーの設定に scroll-into-view を使用しなくなりましたpoint

古いバージョンは

スクロールビュー 1 次元配列 の形式で実装されているため、ページには常に の最後の情報が表示されます。データ追加後のロード であり、ロード前の最後の情報 ではないため、前の開発者は scroll-into-view 属性を として使用しました。データロード後にアンカーポイントを返しますが、スイッチングを指すアンカーポイントとデータロードは同時に発生しないため、リバウンド現象が発生します。

2. 大量のデータの処理

チャット ルーム

機能であるため、ユーザーの会話や画像などのコンテンツを大量に読み込むことは避けられず、scroll-view 自体が大量のデータを読み込むのには適していないため (他の方法を考えるのは残念です)、データの読み込みと表示に力を入れる必要があります

3. 追加機能処理

##チャット ルームには元々 ## がありました#一番下に戻る と他の関数があるため、最適化が完了した後は元の関数を無視することはできません

##OK 開始します~1. スクロール ビューを反転します

なぜ

scroll-view

を反転する必要があるのでしょうか?上記の最初の点から、データを正の順序で挿入する必要がある場合、必然的に

データのロード後に後続のデータを表示できない状況が発生することがわかります

しかし、この状況を解決するには、

scroll-into-view 属性を使用する必要があります。この問題を完全に解決する必要がある場合は、問題の根本である scroll-view## から始める必要があります。 #まずは修正前ののコード?<pre class="brush:php;toolbar:false">&lt;view&gt;这是一个直播画面&lt;/view&gt;   &lt;scroll-view&gt;     &lt;view&gt;       {{ item.data }}     &lt;/view&gt;   &lt;/scroll-view&gt;</pre> <pre class="brush:php;toolbar:false">const scrollIntoView = ref(&quot;index1&quot;); const upper = () =&gt; {   let lastNum = scrollData.value[0].data;   let newArr = [];   for (let index = 1; index  {     scrollIntoView.value = `index${lastNum}`;     console.log(&quot;scrollIntoView  :&gt;&gt;&quot;, scrollIntoView.value);   }, 100); }; const getRandomColor = () =&gt; {   return &quot;#&quot; + Math.random().toString(16).substr(2, 6); };</pre>じゃあ、まずは試してみましょう

スクロールビューの反転

endまず、

scroll -view

Apply a transform:rotate(180deg) 属性を指定し、次に同じ属性を内部の子要素に適用する必要があります。

データを保存する配列##を忘れないでください。#また反転してください。最も重要なことは、

scroll-viewscroll-into-view 属性を削除することです。この効果は得られますか? また、この時点では、 スクロール バー の位置は左側にあります。必要に応じて、

CSS

属性を使用して削除するか、自分でシミュレートします。次の手順は uniapp のスクロールビュー ドロップダウンの読み込みについて話しましょうスクロール バーの CSS スタイルを削除する

?

::-webkit-scrollbar {
  display:none;
  width:0;
  height:0;
  color:transparent;
}
これは単なる です。最初のステップ、次のステップはデータをプルダウンしてロードする方法です。 現時点では、

スクロールビュー反転状態です。つまり、上が下で、下が上です。

(早口言葉は置いといて) そのため、「プルダウン読み込み」を実現するには、以前に使用した

scrolltoupper top メソッド scrollto lowerbottom メソッド に置き換える必要があります 現在の チャット ルーム 見た目はかなり良くなりました

uniapp のスクロールビュー ドロップダウンの読み込みについて話しましょう

2、大量数据的处理

处理完回弹问题后,就需要考虑如何处理大量数据。由于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;
};

来看看效果如何

uniapp のスクロールビュー ドロップダウンの読み込みについて話しましょう

额...似乎没有太大区别,那我们看看页面结构到底也没有将可视区域外的内容切换为空白view

uniapp のスクロールビュー ドロップダウンの読み込みについて話しましょう

成功!

3、功能调整

聊天室原本还有回底功能等,也不能忘了加上

这个部分就比较简单了,只需要直接使用scroll-viewscroll-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 サイトの他の関連記事を参照してください。

声明:
この記事はjuejin.cnで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。