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

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

現象: 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 トランジションを使用した円形ホバー効果のサンプルコード

推薦する

HTML における相対と絶対の使用法と違いの詳細な説明

HTML における相対と絶対の違い: 正直に言うと、HTML は世界で最もシンプルな言語です。タグ言...

Linuxコマンドとファイル検索の詳しい説明

1. ファイル名検索を実行するwhich ('実行可能ファイル' を検索) //PA...

0.1秒の価値!フロントエンドのウェブページの高速化の問題について簡単に説明します

私が現在の仕事の面接を受けたとき、リーダーが真剣にこう言っていたのを覚えています。「今の世の中はイン...

MySQL 中断された接続警告ログの分析

序文:場合によっては、MySQL に接続されたセッションが異常終了することが多く、エラー ログに「通...

tomcat9.exeをクリックするとクラッシュする問題を解決する方法

ある読者から連絡があり、ダウンロードが終了し、操作がまだ開始されていないのに、なぜ Tomcat の...

CocosCreator Typescriptでテトリスゲームを作る

目次1. はじめに2. 解決すべきいくつかの重要な問題3.最後に書く1. はじめに最近、Cocos ...

Linux 上の MySQL 5.7 でパスワードを忘れる問題を解決する

1. 問題Linux 上の mysql5.7 のパスワードを忘れました2. 解決策• ステップ 1:...

MySQL 結合バッファの原理

目次1. MySQL 結合バッファ2. JoinBufferCacheストレージスペースの割り当て3...

MySQL 4 の一般的なマスタースレーブレプリケーションアーキテクチャ

目次1つのマスターと複数のスレーブのレプリケーションアーキテクチャマルチレベルレプリケーションアーキ...

Docker イメージのダウンロードが遅すぎる場合の解決策

Docker イメージのダウンロードが停止したり、遅すぎたりするネットでいろいろな方法を検索しました...

システムエラー 1067 を解決するための MySQL データベース グリーン バージョンのインストール チュートリアル

ソフトウェアのグリーンバージョンとインストールバージョンの違いは何ですか?通常、ファイルのインストー...

yum から docker インストール パッケージをダウンロードし、オフライン マシンにインストールする例の詳細なコード

1. ネットワークマシンでは、デフォルトのcentosyumソースを使用します [root@kole...

Tomcat サーバーの設定と Web プロジェクトの公開に関する IDEA グラフィック チュートリアル

1. Webプロジェクトを作成したら、Tomcatを例にサーバーを構成する必要があります。 2. 実...

ローカルストレージにブール型の値を保存する際の落とし穴を解決する

LocalStorageはブール値を保存します今日、ブール値データを保存するために localsto...

柔軟で安定した高品質の HTML および CSS コード標準を作成するためのガイド

黄金律常に同じコーディング標準セットに従ってください。同じプロジェクトに何人の人が関わっているかに関...