大量のデータを含むエレメントのシャトルボックスで「すべて選択」をクリックするとスタックする問題の解決方法

大量のデータを含むエレメントのシャトルボックスで「すべて選択」をクリックするとスタックする問題の解決方法

現象: 9999 個のデータをレンダリングしました。転送コンポーネントは一度にすべてのデータをレンダリングするため、レンダリングが数十秒間停止するのは正常です。したがって、遅延読み込みまたはページングが基本的な操作であり、ソリューション 2 はページング操作です。

遅延読み込み方式では、EUI の無限スクロールを使用できます: https://element.eleme.cn/

遅延読み込みを行った後でも、「すべて選択」をクリックするのに 6 秒以上かかるため、ソリューション 1 は、遅延読み込みまたはページング操作を行った後でも、ユーザーがページをクリックしたときに数秒の遅延が発生するという問題を解決します。

これは転送ソースコード内の「全選択判定」コードのパフォーマンスが悪いためです。解決策 1 は転送ソースコードを修正することです。

PRを送信しました。アドレスは次のとおりです: hhttps://github.com/ElemeFE/element/pull/20282

解決策1: EUIの転送コンポーネントをコピーして変更し、プロジェクトディレクトリに導入する

EUIの転送コンポーネントディレクトリパス:node_modules\element-ui\packages\transfer、フォルダをコピーして、vueプロジェクトパスに配置します。

EUI の転送が呼び出されるパブリック コンポーネント転送を導入します。

<テンプレート>
  <転送 v-model="値" :data="データ"></転送>
</テンプレート>

<スクリプト>
'../common/transfer' から Transfer をインポートします
エクスポートデフォルト{
  コンポーネント:{
    転送:転送
  },
 //省略</script>

転送コードの変更を開始します。

src/common\transfer\src\transfer-panel.vue コンポーネントを開きます。

updateAllChecked 関数を見つけます。updateAllChecked の機能は、項目をクリックしたときに判断を下す必要があることです。コードのコメントを参照してください。

すべてチェック済みを更新します(){
      /*
        ソースコード this.checkableData はオブジェクトの配列です。必要なのは各オブジェクトのキーです。
        checkableDataKeys はオブジェクトのキーの配列を格納します。これは「クリックして選択できる項目」のコレクションを意味します*/
      start = new Date().getTime(); とします。
      定数 checkableDataKeys = this.checkableData.map(
        アイテム => アイテム[this.keyProp]
      );

      this.allChecked =
        チェック可能なデータキーの長さ > 0 &&
      /*
        2.4.0 以降、変更はありません。開発チームは本当に忙しいと言わざるを得ません。this.checked は、ユーザーが項目をクリックして選択した項目の配列を格納します。
        checkableDataKeys 内のすべての項目に対して this.checked が存在する場合、allChecked は true になりますが、存在しない項目がある場合は false になります。 allChecked はすべてが選択されているかどうかを表します。
        ここでの時間計算量は n^2 ですが、これはナンセンスです*/
      checkableDataKeys.every(item => this.checked.indexOf(item) > -1);
      console.log("updateAllCheckedEnd", 新しい Date().getTime() - 開始);

    },

ソースコードにかかる時間を見てみましょう。

次に、updateAllChecked 関数の書き直しを始めます。

すべてチェック済みを更新します(){
      /*
        変更点 これは、別の配列の要素を含む効率的な配列内の要素オブジェクトを構築するためのアルゴリズムです*/
      start = new Date().getTime(); とします。
      checkableDataKeys を this.checkableData.map((item) => { とします。
        keyProps = {} とします。
        keyProps[item[this.keyProp]] = true;
        keyProps を返します。
      });
      // オブジェクトのkv対応n(1)を使用して、配列に要素が存在するかどうかを確認します。this.allChecked =
        チェック可能なデータキーの長さ > 0 &&
        this.checked.length > 0 &&
        this.checked.every((item) => checkableDataKeys[item]);
      // 上記のコメント付きソースコードが最も時間がかかるので、時間の消費量だけを見てください。console.log("updateAllCheckedEnd", new Date().getTime() - start);
    },

この方法だと、パフォーマンスは大幅に向上します。実際、これは単なる基本的なフロントエンド アルゴリズムの問​​題です。EUI の開発者は怠惰なのでこれを書かなかったようです。

コードを変更した後にかかる時間を見てみましょう。

明らかにはるかに高速です。

次のファイルは\src\common\transfer\src\main.vueで、addToRight関数を見つけます。

右に追加() {
      currentValue を this.value.slice() とします。
      移動先の項目を定数で指定します。
      キーを定数で指定します。
      start = new Date().getTime(); とします。
      // ここには2つのループがあり、時間がかかります this.data.forEach((item) => {
        定数itemKey = item[キー];
        もし (
          this.leftChecked.indexOf(itemKey) > -1 &&
          this.value.indexOf(アイテムキー) === -1
        ){
          移動する項目をpush(itemKey);
        }
      });
      console.log("addToRightEnd", 新しい Date().getTime() - 開始);

      現在の値 =
        this.targetOrder === "シフト解除"
          ? 移動する項目を連結します(現在の値)
          : currentValue.concat(移動する項目);
      this.$emit("入力", currentValue);
      this.$emit("change", currentValue, "right", this.leftChecked);
    },

選択した移動時間:

addToRight関数を修正し、

右に追加() {
      start = new Date().getTime(); とします。
      現在の値を this.value.slice() とします。
      移動する項目を定数で指定します。
      キーを定数で指定します。

      // 変更 let leftCheckedKeyPropsObj = {};
      this.leftChecked.forEach((item, index) => {
        leftCheckedKeyPropsObj[item] = true;
      });

      valueKeyPropsObj を {} とします。
      this.value.forEach((item, index) => {
        valueKeyPropsObj[item] = true;
      });
      this.data.forEach((item) => {
        定数itemKey = item[キー];
        if ( leftCheckedKeyPropsObj[itemKey] && !valueKeyPropsObj[itemKey] ) {
          移動する項目をpush(itemKey);
        }
      });
      console.log("addToRightEnd", 新しい Date().getTime() - 開始);

      現在の値 =
        this.targetOrder === "シフト解除"
          ? 移動する項目を連結します(現在の値)
          : currentValue.concat(移動する項目);
      this.$emit("入力", currentValue);
      this.$emit("change", currentValue, "right", this.leftChecked);
    },

選択した時間を移動します:

時間の消費が大幅に削減されました。このソリューションの前提は、遅延読み込みまたはページングです。100,000 のデータ ボリュームで試してみましたが、それでも良好でした。

解決策2: ページング操作

分析する

checkBox グループには、チェック配列 (選択された項目配列を記録するために使用) と renderItem 配列 (実際にレンダリングされた項目。ページングのため、すべての項目がレンダリングされるわけではありません) があります。`renderItem 配列` の `check 配列` に項目がある場合、その項目は選択済みとしてマークされ、そうでない場合は選択解除されます。実装の原則は、チェック配列と renderItem 配列を単純に比較することです。

ユーザーが「すべて選択」をクリックすると、チェック配列は数万個のデータの配列になります。この時点で 100 個のデータをレンダリングしているため、10000x100 レベルのループを実行する必要があり、時間がかかります。

実際、このページでは 100 個のデータのみがレンダリングされます。一度に何万ものデータをチェック配列に入れる必要はありません。これらの 100 個の配列をチェック配列に入れて、これらの 100 個のデータを選択されたものとして表示するだけで済みます。ページでさらにデータがレンダリングされるときは、チェック配列に新しいデータを追加するだけです。これによりパフォーマンスが大幅に向上します。

プラン

私が採用した解決策は次のとおりです。

1. 表示されるレコードは 100 件のみです。

2. 下に引っ張ると次の 100 個のデータ項目が表示され、上に引っ張ると前の 100 個のデータ項目が表示されます。

3. プルダウンまたはプルアップしてレンダリングデータを増やす場合は、新しいデータをチェック配列に追加します。

これらは単なる一般的なアイデアであり、私はすでにそれらを実装しています。まだ細かいところはたくさん残っています。完璧にしたいなら、オブジェクトのキーと値のペアを使って削除などを実装する必要があります。

これで、データ量が多いときにElementのシャトルボックスがフリーズする問題の解決方法についての記事は終わりです。Elementのシャトルボックスのフリーズの詳細については、123WORDPRESS.COMの以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも123WORDPRESS.COMをよろしくお願いいたします。

以下もご興味があるかもしれません:
  • 要素シャトルフレームのパフォーマンス最適化の実装
  • Vue はオンデマンドでシャトルフレームを転送する要素を導入しました

<<:  HTMLリンクタグのrel属性

>>:  CSS トランジションを使用した円形ホバー効果のサンプルコード

推薦する

テーブルタグ(TAGS)の詳細な紹介

テーブルの基本構文<table>...</table> - テーブルを定義し...

Vueはプログレスバーの変更効果を実現します

この記事ではVueを使ってプログレスバーの変更を簡単に実装してみましたので参考にしてください。具体的...

リクエスト数を制限するために Ajax 同時リクエストを実装するために js を使用するサンプル コード

問題の説明: 非同期リクエストの数が不確定な場合、数百の http リクエストが瞬時に発生したときに...

Docker で MySQL クラスターを構築する方法の例

Docker の基本的な手順:アップデートパッケージ yum -y アップデートDocker仮想マシ...

GolangでMySQLデータベースのバックアップを実装する方法

背景Navicat は、最高の MySQL 視覚化ツールです。ただし、ビューのインポートとエクスポー...

Nginx で Http、Https、WS、WSS を設定する方法

前面に書かれた今日のインターネット分野では、Nginx は最も広く使用されているプロキシ サーバーの...

Vueベースのカスタムコンポーネントを実装してアイコンを導入する

序文プロジェクト開発では、アイコンを使用する方法はたくさんあります。iconfont で適切なアイコ...

DockerHubを自分で構築する方法

先ほど使用したDocker HubはDockerによって提供されています。独自のDockerを構築す...

Vue命令の実装原理の分析

目次1. 基本的な使い方2. 指示の動作原理2.1. 初期化2.2 テンプレートのコンパイル2.3....

MySQL シリーズ 6 のユーザーと認証

目次チュートリアルシリーズ1. ユーザー管理1. ユーザーアカウント2. アカウントの追加と削除3....

Vue マルチページ構成の詳細

目次1. 複数ページの違い2. SPAとMPA 3. Vue Cli スキャフォールディング構成1....

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

1. インストールパッケージMYSQLサービスダウンロードアドレス:MySQL公式サイトからダウンロ...

テーブル内の要素のドラッグと並べ替えの問題について簡単に説明します

最近、要素テーブルを使用すると、並べ替えの問題によく遭遇します。単純な並べ替えであれば、要素の公式が...

MySQL Index Pushdown (ICP) とは何かを理解するための記事

目次1. はじめに2. 原則III. 実践3.1 インデックスプッシュダウンを使用しない3.2 イン...

HTML テーブルタグについての簡単な説明

主にその構造といくつかの重要な特性について説明します。少しずつ改善しながら紹介していきます。 1) ...