バックエンドから返される 100,000 個のデータをフロントエンドでより適切に表示するにはどうすればよいですか?

バックエンドから返される 100,000 個のデータをフロントエンドでより適切に表示するにはどうすればよいですか?

今日はこれについてお話ししましょう。バックエンドが実際に 100,000 個のデータをフロントエンドに返す場合、フロントエンドでそれらをエレガントに表示するにはどうすればよいでしょうか?

予備作業

まず予備作業を行い、その後でテストします。

バックエンド構築

新しいserver.jsファイルを作成し、簡単なサービスを開始し、 10w個のデータをフロントエンドに返し、 nodemon server.jsを通じてサービスを開始します。

nodemonがインストールされていない場合は、まずnpm i nodemon -gでグローバルにインストールできます。

// サーバー.js
定数 http = require('http')
ポート = 8000; 
http.createServer(関数(req, res) {
  // Cors を有効にする
  res.writeHead(200, {
    //ドメイン間で許可されるドメイン名を設定します。すべてのドメイン名を許可するには * を設定することもできます。'Access-Control-Allow-Origin': '*',
    //クロスドメインで許可されたリクエストメソッド。* を設定してすべてのメソッドを許可することもできます "Access-Control-Allow-Methods": "DELETE、PUT、POST、GET、OPTIONS",
    // 許可されるヘッダーの種類 'Access-Control-Allow-Headers': 'Content-Type'
  })
  リスト = []
  数値を0にする
 
  // 100,000件のレコードのリストを生成する
  (i = 0; i < 1000000; i++ とします) {
    数値++
    リスト.push({
      ソース: 'https://p3-passport.byteacctimg.com/img/user-avatar/d71c38d1682c543b33f8d716b3b734ca~300x300.image',
      テキスト: `私はゲスト番号 ${num} の Lin Sanxin です`、
      tid: 番号
    })
  }
  res.end(JSON.stringify(リスト));
}).listen(ポート、関数() {
  console.log('サーバーはポート ' + ポートでリッスンしています);
})

フロントエンドページ

まず新しいindex.htmlを作成します

// インデックス.html
// スタイル <style>
    * {
      パディング: 0;
      マージン: 0;
    }
    #容器 {
      高さ:100vh;
      オーバーフロー:自動;
    }
    .sunshine {
      ディスプレイ: フレックス;
      パディング: 10px;
    }
    画像 {
      幅: 150ピクセル;
      高さ: 150px;
    }
  </スタイル> 
// html 部分 <body>
  <div id="コンテナ">
  </div>
  <script src="./index.js"></script>
</本文>

次に、新しいindex.jsファイルを作成し、これらの10wデータをリクエストするAJAX関数をカプセル化します。

// インデックス.js 
// リクエスト関数 const getList = () => {
    新しい Promise を返します ((resolve, reject) => {
        //ステップ 1: 非同期オブジェクトを作成する var ajax = new XMLHttpRequest();
        //ステップ 2: リクエスト URL パラメータを設定します。パラメータ 1 はリクエスト タイプ、パラメータ 2 はリクエスト URL です。ajax.open('get', 'http://127.0.0.1:8000'); を使用できます。
        //ステップ 3: リクエストを送信する ajax.send();
        //ステップ4: onreadystatechangeイベントを登録します。状態が変化すると、ajax.onreadystatechange = function () {
            ajax.readyState == 4 かつ ajax.status == 200 の場合 {
                //ステップ 5 ここまで到達できれば、データが完全に返され、要求されたページが存在することを意味します。resolve(JSON.parse(ajax.responseText))
            }
        }
    })
} 
// コンテナオブジェクトを取得します。const container = document.getElementById('container')

ダイレクトレンダリング

最も直接的な方法は直接レンダリングすることですが、一度に10wノードをレンダリングするのは非常に時間がかかるため、この方法は絶対にお勧めできません。時間の消費量を見てみましょう。約12秒かかり、非常に時間がかかります。

const レンダリングリスト = 非同期 () => {
    console.time('リスト時間')
    const リスト = getList() を待つ
    リスト.forEach(項目 => {
        定数div = document.createElement('div')
        div.className = 'sunshine'
        div.innerHTML = `<img src="${item.src}" /><span>${item.text}</span>`
        コンテナ.appendChild(div)
    })
    console.timeEnd('リスト時間')
}
レンダリングリスト()

setTimeout ページングレンダリング

この方法は、1ページあたりのページ数limitに応じて、 10w合計Math.ceil(total / limit)ページに分割し、 setTimeoutを使用して毎回1ページのデータをレンダリングします。これにより、ホームページデータのレンダリング時間が大幅に短縮されます。

const レンダリングリスト = 非同期 () => {
    console.time('リスト時間')
    const リスト = getList() を待つ
    console.log(リスト)
    定数合計 = リスト.長さ
    定数ページ = 0
    定数制限 = 200
    const totalPage = Math.ceil(合計 / 制限) 
    const render = (ページ) => {
        if (page >= totalPage) 戻り値
        タイムアウトを設定する(() => {
            (i = ページ * 制限; i < ページ * 制限 + 制限; i++) {
                const 項目 = リスト[i]
                定数div = document.createElement('div')
                div.className = 'sunshine'
                div.innerHTML = `<img src="${item.src}" /><span>${item.text}</span>`
                コンテナ.appendChild(div)
            }
            レンダリング(ページ + 1)
        }, 0)
    }
    レンダリング(ページ)
    console.timeEnd('リスト時間')
}

リクエストアニメーションフレーム

setTimeoutの代わりにrequestAnimationFrameを使用すると、重排の回数が減り、パフォーマンスが大幅に向上します。レンダリングではrequestAnimationFrameより頻繁に使用することをお勧めします。

const レンダリングリスト = 非同期 () => {
    console.time('リスト時間')
    const リスト = getList() を待つ
    console.log(リスト)
    定数合計 = リスト.長さ
    定数ページ = 0
    定数制限 = 200
    const totalPage = Math.ceil(合計 / 制限)
    const render = (ページ) => {
        if (page >= totalPage) 戻り値
        // setTimeout の代わりに requestAnimationFrame を使用する
        リクエストアニメーションフレーム(() => {
            (i = ページ * 制限; i < ページ * 制限 + 制限; i++) {
                const 項目 = リスト[i]
                定数div = document.createElement('div')
                div.className = 'sunshine'
                div.innerHTML = `<img src="${item.src}" /><span>${item.text}</span>`
                コンテナ.appendChild(div)
            }
            レンダリング(ページ + 1)
        }, 0)
    }
    レンダリング(ページ)
    console.timeEnd('リスト時間')
}

ドキュメントフラグメント + requestAnimationFrame

ドキュメントの断片化の利点

1. 以前は、 divタグが作成されるたびにappendChildが呼び出されていました。しかし、ドキュメント フラグメントを使用すると、1 ページのdivタグを最初にドキュメント フラグメントに配置し、次にcontainerappendChild一度に呼び出すことができます。これにより、 appendChild呼び出しの回数が減り、パフォーマンスが大幅に向上します。

2. ページはドキュメントフラグメントで囲まれた要素のみをレンダリングし、ドキュメントフラグメント自体はレンダリングしません。

const レンダリングリスト = 非同期 () => {
    console.time('リスト時間')
    const リスト = getList() を待つ
    console.log(リスト)
    定数合計 = リスト.長さ
    定数ページ = 0
    定数制限 = 200
    const totalPage = Math.ceil(合計 / 制限) 
    const render = (ページ) => {
        if (page >= totalPage) 戻り値
        リクエストアニメーションフレーム(() => {
            // ドキュメントフラグメントを作成する constfragment = document.createDocumentFragment()
            (i = ページ * 制限; i < ページ * 制限 + 制限; i++) {
                const 項目 = リスト[i]
                定数div = document.createElement('div')
                div.className = 'sunshine'
                div.innerHTML = `<img src="${item.src}" /><span>${item.text}</span>`
                // まずドキュメントフラグメントを挿入します。fragment.appendChild(div)
            }
            // 1回限りのappendChild
            コンテナ.appendChild(フラグメント)
            レンダリング(ページ + 1)
        }, 0)
    }
    レンダリング(ページ)
    console.timeEnd('リスト時間')
}

遅延読み込み

より一般的な説明として、 vueフロントエンド プロジェクトを開始し、バックエンド サービスはまだ開いているとします。

実際、実装の原理は非常に簡単です。図で説明しましょう。リストの最後にblankのノードを置き、最初に最初のページのデータをレンダリングし、上にスクロールして、ビューにblank表示されるまで待機します。これは終了を意味します。次に、2 番目のページをロードします。

ビューにblankが表示されるかどうかを判断するには、 getBoundingClientRectメソッドを使用してtop属性を取得します。

<スクリプト設定 lang="ts">
'vue' から { onMounted, ref, computed } をインポートします。
定数getList = () => {
  //上記と同じコード}
const container = ref<HTMLElement>() // コンテナノード const blank = ref<HTMLElement>() // 空白ノード const list = ref<any>([]) // リスト const page = ref(1) // 現在のページ番号 const limit = 200 // 1 ページ表示 // 最大ページ数 const maxPage = computed(() => Math.ceil(list.value.length / limit))
// 実際に表示されるリスト const showList = computed(() => list.value.slice(0, page.value * limit))
const ハンドルスクロール = () => {
  // 現在のページ番号と最大ページ番号の比較 if (page.value > maxPage.value) return
  const clientHeight = コンテナ.value?.clientHeight
  定数 blankTop = blank.value?.getBoundingClientRect().top
  if (clientHeight === blankTop) {
    // ビューに空白が表示され、現在のページ番号が 1 増加します
    ページ.値++
  }
} 
onMounted(非同期() => {
  const res = getList() を待つ
  リスト.値 = res
})
</スクリプト> 
<テンプレート>
  <div class="コンテナ" @scroll="handleScroll" ref="コンテナ">
    <div class="sunshine" v-for="(item) in showList" :key="item.tid">
      <img :src="item.src" />
      <span>{{ 項目.テキスト }}</span>
    </div>
    <div ref="空白"></div>
  </div>
</テンプレート>

上記は、バックエンドから返された 10 万個のデータをフロントエンドでより適切に表示する方法についての詳細です。バックエンドから返された 10 万個のデータをフロントエンドで表示する方法の詳細については、123WORDPRESS.COM の他の関連記事に注目してください。

以下もご興味があるかもしれません:
  • JavaScript で一度に数万件のデータを一括表示する方法
  • 大量のデータに対する js フロントエンド表示および処理方法
  • Javaはフロントエンドでバックグラウンドデータの表示を実現します
  • フロントエンドとバックエンドのデータインタラクションを実装する方法の概要

<<:  HTML のテキストエリアの改行問題の概要

>>:  有名なブログの再設計例 28 件

推薦する

MySQL 条件付きクエリと使用法および優先順位の例の分析

この記事では、例を使用して、MySQL 条件クエリ and or の使用方法と優先順位を説明します。...

Vue.js の計算プロパティ、監視プロパティ、ライフサイクルの詳細な説明

目次序文計算されたプロパティ計算プロパティの紹介入門ケース統計価格事例ゲッターメソッドとセッターメソ...

MySQL インデックスの長所と短所、およびインデックス作成のガイドライン

1. インデックスを作成する理由(メリット)インデックスを作成するとシステムのパフォーマンスが大幅に...

実務経験7年のフロントエンドスーパーバイザーによる経験共有

今日はベテランの貴重な経験を共有します。著者は技術管理の経験が7年あり、多い時は80人以上を率いてい...

Vue の get リクエストと post リクエストの違いのまとめ

このチュートリアルの動作環境: Windows 7 システム、vue 2.9.6 バージョン、DEL...

GobangゲームのWebバージョンを実装するためのJavaScript

この記事では、GobangゲームのWebバージョンを実装するためのJavaScriptの具体的なコー...

フロントエンドの vue+express ファイルのアップロードとダウンロードの例

新しいserver.jsを作成する糸初期化 -y 糸を追加エクスプレスノードモン -D var ex...

MySQL 5.7.21 解凍版のインストールと設定方法のグラフィックチュートリアル (win10)

MySQL 5.7.21 解凍版のインストールと設定方法は参考までに。具体的な内容は以下のとおりで...

ウェブデザイナーが注意すべき 43 のウェブデザインの間違い

これはウェブサイトのユーザビリティに関する記事です。著者は自身の経験に基づいて、ウェブサイトのデザイ...

クールなネオンライト効果を実現する純粋な CSS (デモ付き)

私は最近、YouTube の CSS アニメーション効果チュートリアル シリーズをフォローしています...

Web フォントの読み込みを最適化する方法をご存知ですか?

タイトル通りです!一般的に使用される font-family はブラウザの組み込みフォントを読み込み...

MYSQL 演算子の概要

目次1. 算術演算子2. 比較演算子3. 論理演算子4. ビット演算子5. 演算子の優先順位1. 算...

MySQL 8.0.19 のインストールと設定方法のグラフィックチュートリアル

この記事は、参考のためにMySQL 8.0.19のインストールと設定のグラフィックチュートリアルを記...

Dockerコンテナのエクスポートとインポートの例

目次DockerコンテナのエクスポートDockerコンテナのインポ​​ートこの記事では主に、コンテナ...

node.js グローバル変数の具体的な使用法

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