13-Vue の長いリストの最適化 vue-virtual-scroller

答え:

大規模なエンタープライズ レベルのプロジェクトでは、大量のデータがレンダリングされることがよくあります。この種の長いリストは非常に一般的なシナリオです。リストの内容が増加すると、ページ スライドのフリーズや画面が白くなるなどの問題が発生します。データのレンダリング遅い

この状況は主に、小さなプログラム、モバイル端末、またはバックグラウンド管理ページで発生します。

通常、ページングを使用してコンテンツを徐々に取得しますが、コンテンツが増えていくと、

たとえば、モバイル端末でプルダウンを更新すると上にスクロールし続け、下部にコンテンツが読み込まれるため、リストに多くの要素が追加され、要素が増えるとブラウザが並べ替えられて再描画されます。 、メモリ占有であれGPU レンダリングであれ、パフォーマンスが大幅に低下し、ページ スライドのフリーズデータ レンダリングの遅延が発生します。

状況に応じて異なる処理を行う必要があります。

  • 大量のデータを避ける: 取得するにはページネーションが必要です
  • 大量のデータのレンダリングを避ける: vue-virtual-scrollerプラグインおよびその他の仮想リストソリューションは、ビューポート範囲内のデータのみをレンダリングします。
  • 更新を避ける: v-onceを使用して1 回だけレンダリングします
  • 最適化された更新: v-memoを通じてサブツリーをキャッシュし、条件付きで更新し、再利用を改善し、不必要な更新を回避します。
  • データをオンデマンドでロードする:ツリーコンポーネントのサブツリーの遅延ロードなどの遅延ロードを使用します。

つまり、やはり特定のニーズに依存します。まず、デザインからの大規模なデータの取得とレンダリングを避けます。これを本当に行う必要がある場合は、仮想リストを使用してレンダリングの数を最適化し、最後に更新を最適化します。 -memoを使用すると、ビッグ データ更新のパフォーマンスをさらに最適化できます。その他の方法としては、対話型の最適化、無限スクロール、遅延読み込みソリューションなどを使用できます。

ページラグの原因

根本原因: 多数の DOM 要素のリフローと再描画

変更は現在の DOM 要素に対する変更ですが、更新はすべての DOM 要素を更新します。

最適化のアイデア:

1. 遅延レンダリング
  • 一般的なロングリスト最適化ソリューションである遅延読み込みは、モバイル端末では一般的です
  • 原則: 一度に一部のみがレンダリングされ、レンダリングされたデータがスクロールされようとすると、次の部分がレンダリングされます。
  • 利点: 毎回データの一部を高速にレンダリングします。
  • 短所: データ量が多い場合、ページ内に多数の DOM ノードが存在するため、メモリが過剰に消費され、ブラウザのレンダリング パフォーマンスが低下し、ページがフリーズします。
  • 利用シナリオ:データ量が大きくない場合(各データの複雑さに応じて1000個など)
2. ページのレンダリング

通常、バックエンドはデータを提供します。ページ数と各ページに表示されるデータの量をバックエンドに渡すだけで、バックエンドは表示するデータを提供します。

3. 視覚領域のレンダリング

原則: ページの表示領域のリスト項目のみがレンダリングされ、非表示領域のデータは「まったく表示されません」(最初のいくつかの項目と次のいくつかの項目はプリロードされます)、リスト項目はリストをスクロールすると動的に更新されますが、白画面になるのを防ぐため、実際にはさらにいくつかのデータが読み込まれます。

ビューポートレンダリングを自分で実装する

親コンポーネント内で

  • 計算キャッシュを使用して 10,000 個のデータをシミュレートします。
  • item (データ)、size (各データの高さ)、showNumber (毎回レンダリングされるデータの数) をプロパティ バインディングを通じてサブコンポーネントに渡します。

サブコンポーネント内

  • 親コンポーネントから props を通じて渡されたプロパティを受け取ります。
  • 一番外側のボックスは、垂直スクロールを実現するために、overflow-y:scroll; に設定されています。
  • 最も外側のボックスの固定高さ (最も外側のボックスの高さ = サイズ * showNumber);
  • 外側のボックスのスクロール イベントをリッスンし、ロールアップされるデータの高さを計算します。
  • 表示領域内のデータの開始インデックスを計算します。start = ロールされた高さ/単一のデータの高さです。
  • 表示可能領域内のデータの終了インデックスを計算します。終了 = 開始インデックス + 表示可能領域に表示できる項目の数です。
  • 表示領域の開始インデックス start と終了インデックス end のデータを取得し、表示領域に表示します。

親コンポーネント

10,000個のデータをシミュレート

10,000 個の要素を持つ空の配列を作成し、fill() 関数を使用して初期化します。すべての値は空です。その後、map を使用して ID とコンテンツを配列に返します。これにより、配列の割り当てが実現されます。

computed: {
	item () {
		return Array(10000).fill('').map((item, index) => ({
			id: index,
			content: `列表内容`+ index
		}))
	}
}

 サブアセンブリ

UI構造

list は表示される領域です

バーはボックスを開き、垂直方向にスクロールできるようにします。

  • 視覚領域コンテナ: すべての要素を保持する下部のボックスとして表示されます。
  • スクロール可能領域: 中間層とみなすことができ、データが 10000 個あり、各リスト項目の高さが 50 であるとすると、スクロール可能領域の高さは 10000 * 50 になります。このレイヤーの要素は非表示であり、目的は実際のリストとまったく同じようにスクロール バーを作成することです。
  • ビジュアルエリアリスト: 現在処理されているデータを表示する最上位レイヤーとみなすことができ、高さはビジュアルエリアコンテナと同じです。可視領域リストが常に可視領域に表示されるように、可視領域リストの位置が動的に変更されます。

上記の概念を理解した後、スクロール バーがスクロールするときに何をする必要があるかを見てみましょう。

  1. スクロールの距離と item 高さに応じて、表示する必要がある現在のリストを計算します startIndex
  2. 表示可能領域の高さに応じ startIndex て、現在表示されるリストの高さを計算します endIndex
  3. 対応するリストデータに応じてインターセプトし startIndex 、 endIndex 表示可能領域リストに割り当て、ページ上にレンダリングします。
  4. スクロール距離と item 高さに応じて、表示領域リストのオフセット距離を計算し startOffset、リストに設定します

 

 親コンポーネントから渡されたデータを受け取り、最初の添え字と終了添え字を定義します。

コンテナの高さとロールされたデータの高さを計算します

コンテナのスクロール イベントを監視します。最初の添え字は、ロールされたデータ ストリップの数を切り捨てたものです。

終了添え字は開始添え字 + 表示するデータ項目の数です。

仮想リスト vue-virtual-scrollerを使用して実装

長いリストの場合、ほとんどの操作は次のとおりです。

1. 遅延読み込み、ページネーション、

2. Object.freeze は配列をフリーズして応答をキャンセルします。これは、ほとんどの場合応答が表示されるためです。

3. 高解像度の画像をサムネイルに置き換えます。多くの場合、長いリスト内の画像のサイズは比較的小さいため、代わりに小さな画像を使用できます。

ページネーションの場合、上記の方法で長いリストの問題のほとんどを解決できます。

ページネーションが不可能な場合は、表示領域にレンダリングします

アイテムの高さは固定されています (RecycleScroller)

プラグインをダウンロード

yarn add vue-virtual-scroller --save

 main.jsに登録する

import "vue-virtual-scroller/dist/vue-virtual-scroller.css";
import VueVirtualScroller from "vue-virtual-scroller";

Vue.use(VueVirtualScroller);

 以下が必要です

小道具

説明する

デフォルト

アイテム
表示領域に描画されるデータのリスト --
アイテムサイズ
各データの高さ ヌル
スタイル
可視領域の外箱の高さ --
v スロット = { アイテム }
スロット、各データ項目を取得 --

 必要に応じて変更します

小道具

説明する

デフォルト

プリレンダリング
毎回レンダリングするデータの数をサーバー (SSR) に指示します。 0
バッファ
空白スクロールを避けるための、表示領域外のマルチレンダリングのデータ高さ 200
キーフィールド
アイテムを識別し、レンダリングされたビューを最適に管理するためのフィールド ID

固定高さスコープのスロット パラメータ

スロット

説明する

デフォルト

アイテム
各データ --
索引
各データの添え字 --
アクティブ
ビューがアクティブかどうか。アクティブなビューは表示可能なビューとみなされ、RecycleScroller によって配置されます。非アクティブなビューは表示されているとは見なされず、ユーザーに対して非表示になります。ビューが非アクティブな場合は、レンダリング関連の計算をスキップする必要があります。 --

アイテムの高さは固定されており (RecycleScroller)、引き上げてロードすることができます

イベント

説明する

デフォルト

サイズ変更
サイズが再計算されるときにトリガーされます --
見える
スクロールバーがページ内に表示されていると判断したときに発生します。 --
隠れた
スクロールバーがページ内で非表示になったときにトリガーされます --
update (startIndex、endIndex)
 : EmitUpdate="true"場合のみ、ビューが更新されるたびに発行されます。 間違い

実装アイデア:

  • :emitUpdate="true" および @update イベントを追加します。
  • update 関数は、start と end の 2 つの仮パラメータを渡し、end が配列リストの長さと等しいと判断して、インターフェイスに新しいデータの取得を要求し、配列に追加します。

 アイテムの高さは固定されていません (DynamicScroller)。引き上げてロードすることができます

Props(参数)

解释

默认值

item(必填)
每项数据 --
active(必填)
保持视图,数据处于 active 状态,将防止不必要的大小重新计算。 --
sizeDependencies
影响高度的值,如果发生变化,则重新计算 --
watchData
深入监视更改以重新计算大小(不推荐,可能会影响性能) false
tag
组件要呈现的元素 div
emitResize
每次重新计算大小时发出事件(可能会影响性能) false
minItemSize
列表项初次渲染使用的最小高度

Events(事件)

解释

默认值

resize
重新计算大小时触发,仅当 :emitUpdate=“true” false

小程序长列表优化实践 - 知乎

おすすめ

転載: blog.csdn.net/iaz999/article/details/131527796