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プロトタイプチェーン図のまとめと実践

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

推薦する

Linux で実行中のすべてのプロセスを表示する方法

ps コマンドを使用できます。プロセスの PID など、現在実行中のプロセスに関する関連情報を表示で...

シーケンス関数を実装する MySQL コード

MySQLはシーケンス関数を実装する1. シーケンスレコードテーブルを作成する テーブル `sys_...

Web デザイン体験: 5 つの優れた Web デザイン コンセプトの完全分析 (画像)

他の種類のデザインとは異なり、Web デザインは時代の発展とともに常に変化しています。したがって、W...

JavaScriptのプロトタイプオブジェクトを徹底的に理解しましょう

目次1. プロトタイプとは何ですか? 1.1 関数プロトタイプオブジェクト1.2 コンストラクタを使...

Win10 + Ubuntu 16.04 デュアルシステム 完璧なインストールチュートリアル [詳細]

必ずデータをバックアップすることを忘れないでください。データは貴重なものです! ! !コンピュータモ...

JavaScript Promise の徹底解説

目次1. Promise とは何ですか? 2. なぜ Promise が存在するのでしょうか? 3つ...

MySQL 8の新機能におけるグローバルパラメータの永続性の詳細な説明

目次序文グローバルパラメータの永続性最後に要約する参考資料:序文2018 年に MySQL 8.0....

Vueはブラウザ側のコードスキャン機能を実装します

背景少し前にブラウザカメラの取得とスキャンコード認識の機能を作りました。その際の知識ポイントと具体的...

dockerfile-maven-plugin 使用ガイドの概要

目次pom 構成Setting.xml 構成ログインステータスログインが必要ですログインは必要ありま...

MYSQLでリモートアクセス権限を有効にする方法

1. MySQLデータベースにログインするmysql -u ルート -pユーザーテーブルを表示する ...

CSSでよく使われるフォントスタイルを設定することで様々なフォントの変更が可能(例詳細説明)

CSS フォント プロパティは、テキストのフォント ファミリ、サイズ、太字、スタイル (斜体など)...

Nginx でアンチホットリンクを設定するための手順を完了する

必要:通常、サイト側は、ウェブサイト上の動画や写真が盗まれるのを防ぎたいと考えています。結局のところ...

JavaScript ESの新機能letとconstキーワードに基づく

目次1. letキーワード1.1 基本的な使い方1.2 変動昇進はない1.3 一時的なデッドゾーン1...

優れたウェブワイヤーフレーム設計・制作ツール13選を紹介

プロジェクトの作業を開始するときは、ワイヤーフレームを使用してアイデアをスケッチすることが重要です。...

MySQL データベース データのロード 複数の用途

目次MySQL Load Dataの多様な用途1. LOAD の基本的な背景2. 基本パラメータをロ...