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

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

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

推薦する

純粋な CSS3 を使用して、円の動的な光る特殊効果アニメーションを実装するためのサンプル コード

この記事では、主に、円形のダイナミックな光る特殊効果アニメーションを実現するための純粋な CSS3 ...

Tencent インタビュー: SQL ステートメントの実行が非常に遅くなる理由は何ですか? ---後悔シリーズは見ないで(推奨)

正直に言うと、この質問には MySQL のコア知識がかなり必要で、コンピュータ ネットワークの知識を...

Linux パーティションまたは論理ボリュームにファイルシステムを作成する方法

序文システムにファイル システムを作成し、それを永続的または非永続的にマウントする方法を学習します。...

MySql インデックスの詳細な紹介と正しい使用方法

MySql インデックスの詳細な紹介と正しい使用方法1. はじめに:インデックスはクエリ速度に重大な...

初心者がdockerにmysqlをインストールするときに遭遇するさまざまな問題

序文最近、パソコンのシャットダウンに時間がかかることが多く、強制的にシャットダウンするには電源ボタン...

WeChatアプレットがテキストスクロールを実装

この記事の例では、WeChatアプレットでテキストスクロールを実装するための具体的なコードを参考まで...

デザイン理論:テキスト表現とユーザビリティ

<br />テキストデザインでは、通常、テキストのレイアウト、つまりテキストをより美しく...

Docker+daocloudはフロントエンドプロジェクトの自動構築とデプロイを実現します

自動プロジェクト展開は大企業やユニコーン企業でよく使用され、手動でプロジェクトを展開するよりも効率的...

MySQL 8.0 以降の一般的なコマンドの詳細な説明

リモートアクセスを有効にする次のコマンドを実行して、root ユーザーのリモート アクセス権を有効に...

JavaScriptの浅いコピーと深いコピーについての簡単な説明

目次1. 直接譲渡2. 浅いコピー3. ディープコピー1. JSONオブジェクトメソッド2. 再帰コ...

Vue Element フロントエンドアプリケーション開発 従来の Element インターフェースコンポーネント

目次1. リストインターフェースとその他のモジュールの表示処理2. 従来のインターフェースコンポーネ...

MySQL 起動時に「サーバーは PID ファイルを更新せずに終了しました」というエラーが報告される理由の詳細な分析

多くの人が MySQL の起動時にこのエラーに遭遇しています。まず、このエラーの前提は、サービス ス...

jQueryカルーセル機能を実装する方法

この記事では、jQueryカルーセル機能の実装コードを参考までに共有します。具体的な内容は次のとおり...