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

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

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

推薦する

InnoDB がシリアル化分離レベルを実装する方法

シリアル化の実装InnoDB は 2 つの方法でシリアル化を実装します。まず、SELECT 文が明示...

Linux で open-vswitch をインストールおよびアンインストールする方法

1. ソースコードからovsをコンパイルしてインストールします。依存関係をインストールします: # ...

TCPパフォーマンスチューニングの実装原理とプロセス分析

3ウェイハンドシェイクフェーズクライアントSYNパケットの再試行回数sysctl -w net.ip...

Dockerfileの指示と基本構造の説明

Dockerfile を使用すると、ユーザーはカスタム イメージを作成できます。基本構造Docker...

JS でタブ効果を書く

この記事の例では、タブ効果を記述するためのJSの具体的なコードを参考までに共有しています。具体的な内...

HTML TextArea でのフォーマット保存の問題の解決方法

textarea の形式は保存時にデータベースに保存できますが、表示時には /n と相互に変換できな...

HTTPS の有効化に関する経験の共有

国内のネットワーク環境が悪化し続ける中、さまざまな改ざんや乗っ取りが後を絶たず、サイト全体をHTTP...

mysql 5.7.18 winx64 パスワード変更

MySQL 5.7.18 が正常にインストールされた後、バージョン 5.7 では空のパスワードでのロ...

JavaScript は、シンプルな虫眼鏡の最も完全なコード分析を実装します (ES5)

この記事では、参考までに、シンプルな虫眼鏡を実装するためのJavaScriptの具体的なコードを紹介...

Docker Compose のサイドカーモードの詳細な説明

目次Docker Composeとは要件に不適切な言語が使用されている実装Docker Compos...

Vue2.x プロジェクトのパフォーマンス最適化のためのコード最適化の実装

目次1 v-ifとv-showの使用2. 計算と監視を区別する3 v-for トラバーサルでは、アイ...

Dockerfileを使用してDockerイメージを構築する手順

Dockerfile は、命令を含むテキスト ファイルです。各命令はレイヤーを構築するため、各命令の...

Vue3.0はvue-grid-layoutプラグインを使用してドラッグレイアウトを実装します。

目次1. プラグイン2. 幕間3. 実装4. 検証機能1. プラグインまず、私たちが選んだプラグイン...