n 個のコンテナ要素による無限スクロールの実装コード

n 個のコンテナ要素による無限スクロールの実装コード

シナリオ

最大 10000 要素のリストを正しくレンダリングする方法。

無限ドロップダウン読み込みテクノロジーにより、ユーザーは大きなコンテンツ ブロックを表示するためにスクロールし続ける必要があります。このアプローチでは、下にスクロールするたびに新しいコンテンツが継続的に読み込まれます。

スクロールをデータを発見する主な方法として使用すると、ユーザーがページに長く留まり、ユーザーのエンゲージメントが向上します。ソーシャル メディアの普及により、ユーザーによって大量のデータが消費されるようになりました。無限スクロールにより、ユーザーはページのプリロードを待たずに大量の情報を効率的に閲覧できるようになります。

考え方を変えて、ページが 10,000 個の全幅コンポーネントで構成されている場合、5 つのコンポーネントを使用してページ全体を動的にレンダリングするにはどうすればよいでしょうか。

解決

ページング、遅延読み込みなど、長いリストを最適化するためのソリューションは多数あります。 非常に良いインタラクション(菊の絵)があり、ユーザーは待つことができます。この計画も大成功でした。

別のアプローチを見つけるにはどうすればよいでしょうか?

1. シングルページアプリケーションで、ページングソリューションを分析できますか?ページごとに10個の要素があり、各ページングは​​10個の要素を次のようにレンダリングします。

2. 括弧を使用してリスト全体の長さをサポートし、画面が対応する位置までスクロールしたときに対応する 10 個の要素をレンダリングできますか?

ちらつきの問題

このアイデアを実装すると、ちらつきの問題が発生します。スクロール イベントが頻繁に発生するため、遷移するたびにレンダリングする必要がある 10 個の要素を見つけて直接置き換えるため、表示される要素が常に再描画されます。

ここでのアイデアは、画面上の見える位置に 10 個をレンダリングし、次に上方向と下方向に 10 個のレンダリングを導出して、合計 30 個にすることです。レンダリングを制御するときは、常に上部または下部の要素を置き換えて、中央に見える部分を再描画する必要がないようにする必要があります。事前にレンダリングされたデータを再描画するだけです。

原理

5 要素の固定ウィンドウ サイズで n 項目のリストを表示できるコンポーネントを実装します。つまり、いつでも、無限スクロール n 要素上に 5 つの DOM コンテナーのみがあります。

 <ul>
        <li style="transform: translate3d(0px, 0px, 0px);">……</li>
        <li style="transform: translate3d(0px, 60px, 0px);">……</li>
    </ul>
  • 長いリストの内容は、通常、規則的なパターンを持っています。このリストの高さは、<li> の数によって直接計算できます。たとえば、要素が 1000 個あり、各要素の高さが 60 ピクセルの場合、リスト全体の高さは 60000 ピクセルであることがすぐにわかります。
  • コンテナを作成した後、内部の <li> は <ul> に対して絶対位置に配置され、js を使用して各 <li> の対応する 'transform: translate3d(0px, 0px, 0px);' 属性を直接計算します。
  • スクロール時間を監視することで、現在の位置でレンダリングする必要がある<li>を継続的に見つけ、それを以前のレンダリングデータセットと比較し、同じ<li>をスキップし、以前のレンダリングデータセットとは異なる要素を見つけて、対応する置き換えを行うことができます。

たとえば、要素が 100 個あり、ホームページに表示されるのは 5 個だけです。最初は、[0,1,2,3,4] 個の 5 つの <li> をレンダリングする必要があります。少し下にスクロールすると、[1,2,3,4,5] 個の <li> をレンダリングする必要があります。このとき、要素全体を直接置き換えるのではなく、差分項目のみを置き換えます。構造は [5,1,2,3,4] である必要があります。絶対位置に配置されているため、標準フローから外れます。1 回の再描画は他の 4 つに影響を与えないため、パフォーマンスが向上します。

達成方法

<!DOCTYPE html>
<html lang="ja">

<ヘッド>
  <メタ文字セット="UTF-8">
  <meta name="viewport" content="width=デバイス幅、初期スケール=1.0">
  <meta http-equiv="X-UA-compatible" content="ie=edge">
  <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
  <title>ドキュメント</title>
  <スタイル>
    体、
    ウル、
    li {
      マージン: 0;
      パディング: 0;
      リストスタイル: なし;
    }

    ul {
      位置: 相対的;
    }

    ul li {
      位置: 絶対;
      上: 0;
      幅: 100%;
      高さ: 31px;
      行の高さ: 32px;
      下境界線: 1px 実線 #ccc;
    }
  </スタイル>
</head>

<本文>
  <ul>
  </ul>
</本文>
<スクリプト>
  // コンテナの合計 var list = [];
  // 表示範囲内の要素コンテナ var showList = [];
  // レンダリングコンテナ var renderList = [];
  // 各コンテナの高さ var lineHeight = 32

  // 1000 要素を初期化します for (var i = 0; i < 1000; i++) {
    list.push({ id: i, text: '第' + (i + 1) + '個要素', top: i * lineHeight, bottom: (i + 1) * lineHeight })
  }
  // コンテナの高さを初期化します $('ul').attr('style', 'height:' + 1000 * lineHeight + 'px')
  // コンテナを初期化する関数を見つける render(top, bottom) {
    表示リスト = []
    // レンダリングされたデータでどのデータが繰り返されるかをマークし、この部分は繰り返しレンダリングされません var sameIndex = []
    // スクロール位置がどの要素にあるか調べる var currentIndex = 0
    (var i = 0; i < list.length; i++) の場合 {
      var アイテム = リスト[i]
      (item.top <= window.scrollY && item.bottom > window.scrollY){
        現在のインデックス = i;
        壊す;
      }
    }
    変数範囲 = 0
    // 現在見つかった要素の上下に表示される要素を、合計数が 35 に達するまで検索します while (range < 100 && showList.length + sameIndex.length < 35) {
      if (currentIndex - 範囲 >= 0) {
        // 条件を満たす要素がレンダリングされたリストにあるかどうかを比較します。ある場合はマークします。ない場合は showList に入れて、その時点でマークされていない要素を置き換えます。if (renderList.includes(list[currentIndex - range].id)) {
          // sameIndex.push(現在のインデックス範囲)
          sameIndex.unshift(renderList.indexOf(リスト[現在のインデックス - 範囲].id))
        } それ以外 {
          showList.unshift(リスト[現在のインデックス - 範囲])
        }
      }

      (currentIndex + range < list.length && range != 0) の場合 {
        if (renderList.includes(list[currentIndex + range].id)) {
          sameIndex.push(renderList.indexOf(リスト[現在のインデックス + 範囲].id))
        } それ以外 {
          showList.push(リスト[現在のインデックス + 範囲])
        }
      }
      範囲++
    }
    // レンダリングする必要がある新しい要素を、レンダリングリスト内のマークされていない要素に置き換えます。if (renderList.length > 0) {
      (var i = 0; i < renderList.length; i++) {
        if (!sameIndex.includes(i) && showList.length) {
          レンダリングリスト[i] = showList.shift().id
          $('ul li').eq(i).html(list[renderList[i]].id + list[renderList[i]].text).attr('style', 'transform: translate3d(0px, ' + list[renderList[i]].top + 'px, 0px);')
        }
      }
    } それ以外 {
      // リストを初めて初期化する renderList = showList.map(function (val) { return val.id })
      renderList.map(関数 (キー) {
        $('ul').append($('<li style="transform: translate3d(0px, ' + list[key].top + 'px, 0px);"">#' + list[key].id + list[key].text + '</li>'))
      })
    }
    コンソールログ(レンダリングリスト)
  }
  // 最初のレンダリング render()
  $(window).scroll(関数(e) {
    与える()
  });

</スクリプト>

</html>

やるべきこと

  1. コンテナ要素を置き換える方法と比較すると、常に最適化できると感じられ、操作効率が向上し、高速スクロール時に表示される白い画面を最適化できます。
  2. ここで考える問題[0,1...,10000]があります。毎回5つの要素を取り出し、新しく選択された要素を古い要素と比較し、2つの配列の交差部分を保持し、古い配列の交差していない部分を新しい配列の新しい要素に置き換えます。たとえば、1回目が[0,1,2,3,4]で、2回目が[2,3,4,5,6]の場合、比較により[5,6,2,3,4]が生成され、3回目が[4,5,6,7,8]の場合、生成される値は[5,6,7,8,4]です。最小限のコードでこの結果配列を取得します。

まとめ

  1. データによるレイアウトと初期化を完了する
  2. コンテナを標準フローから外して配置する
  3. データを比較することで、異なるコンテナ要素を見つけ出し、毎回できるだけ少ないコンテナ要素を再描画することができます。

次号-----長いリストを実現するためのコンポーネントの配置

要点

  1. コンポーネントは通常のリストとは異なります。コンポーネントの高さは制御できない場合があり、モバイル デバイスによって異なる場合があります。
  2. コンポーネントの高さが異なるため、レンダリング領域内のコンポーネントの数も異なり、コンテナーの数も異なります。
  3. 高さはデータから直接計算するのは簡単ではありません。全体のレンダリングが必要で、その後 DOM を通じて位置と高さを計算すると、最初の読み込みパフォーマンスが消費されます。

以上がこの記事の全内容です。皆様の勉強のお役に立てれば幸いです。また、123WORDPRESS.COM を応援していただければ幸いです。

<<:  JavaScriptプロトタイプチェーン図のまとめと実践

>>:  位置固定オフセット問題を解決する方法の詳細な説明

推薦する

JSを使用して簡単な計算機を実装する

JSを使用して、参考用の簡単な計算機を完成させます。具体的な内容は次のとおりです。要件: 入力値は数...

MySQL の重複データの処理方法 (防止と削除)

一部の MySQL テーブルには重複レコードが含まれている場合があります。重複データが存在することを...

Linux TTY/PTS の違いの概要

キーボードで文字を入力すると、対応するプロセスにどのように送信されるのでしょうか? ps や who...

Linux での MySQL 5.6.33 のインストールと設定のチュートリアル

このチュートリアルでは、LinuxでのMySQL 5.6.33のインストールと設定方法を参考までに紹...

Tomcat での jar のロードに関する異常な問題の分析と解決

現象の説明:プロジェクトでは、Springboot を使用して Web プロジェクトを開始します。起...

Nodejs のグローバル変数とグローバルオブジェクトの知識ポイントと使用方法の詳細

1. グローバルオブジェクトすべてのモジュールは呼び出すことができます1) global: ブラウザ...

JavaScript でツリー構造を構築するための効率的なアルゴリズムについての簡単な説明

目次導入アイデアID配列インデックスのマッピング関係を確立するツリー構造の構築原理要約する導入組織階...

VirtualBox を使用して Linux クラスターをシミュレートする方法

1. ホストMacbookにHOSTをセットアップする前回のドキュメントでは仮想マシンの静的 IP ...

Alibaba Cloud ECS クラウド サーバー (Linux システム) は、MySQL をインストールした後にリモートで接続できません (落とし穴)

昨日、1年間使用していた Alibaba Cloud サーバーを購入しました。システムは Linux...

Tomcat のメモリ構成の正しい姿勢についての簡単な説明

1. 背景多くのブログや記事を読みましたが、JVM のメモリ割り当て方法に関する包括的な記事は見つか...

And キーワードを使用した MySQL の複数条件クエリ ステートメント

AND キーワードを使用した MySQL 複数条件クエリ。MySQL では、AND キーワードを使用...

VMware 仮想マシンのインストール win7 オペレーティング システム チュートリアル ダイアグラム

VMwareaのインストールプロセスは説明しませんが、主にwin7イメージをロードする方法を説明しま...

Robots.txtの詳細な紹介

robots.txt の基本的な紹介Robots.txt はプレーンテキスト ファイルであり、Web...

Linux C バックグラウンドサービスプログラムの単一プロセス制御の実装

導入通常、バックグラウンド サーバー プログラムには 1 つのプロセスのみが必要ですが、単一のプロセ...

React Nativeでaxiosを使用してネットワークリクエストを行う方法

フロントエンド開発では、Ajax、jQuery ajax、axios、fetch など、データ要求を...