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

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

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

推薦する

MySQL実践スキル: 2つのテーブルに異なるデータがあるかどうかを比較する方法の分析

この記事では、MySQL が 2 つのテーブルを比較して、異なるデータがあるかどうかを確認する方法を...

VMware15 の Deepin インストール詳細チュートリアル (画像とテキスト)

序文Deepin のユーザー インターフェイスは、使用時に非常に見栄えがします。インターフェイス効果...

CSS flex 複数列レイアウト

基本的な3列レイアウト 。容器{ ディスプレイ: フレックス; 幅: 500ピクセル; 高さ: 20...

Mapper SQL ステートメント フィールドとエンティティ クラス属性名の関係は何ですか?

背景: 1. データベースに通知テーブルがある あなたは見ることができますgmt_create、通知...

Linuxのsortコマンドの複数のパラメータを理解するための1つの質問

sort コマンドは非常によく使用されますが、-o、-n、-u、-r などの多くのパラメーターがあり...

MySQL SQL文を最適化するためのヒント

十分に最適化されていない、またはパフォーマンスが極端に低い SQL ステートメントに直面した場合、通...

MySQL のデバッグと最適化に関する 101 のヒントを共有する

MySQL は強力なオープンソース データベースです。データベース駆動型アプリケーションの数が増える...

Tomcatc3p0 で jnid データ ソースを構成する 2 つの実装方法の分析

c3p0の使用c3p0jarパッケージをインポートする <!-- https://mvnrep...

Nginxのアクセス制限設定の詳細な説明

Nginxのアクセス制限設定とはNginx のアクセス制限は、IP ベースのアクセス制御とユーザーベ...

CSSのline-heightとheightの詳細な説明

最近、CSS インターフェースに取り組んでいるときに、line-height と height とい...

WeChatアプレットの入力レベルとテキストエリアレベルの浸透率が高すぎる問題の解決策

WeChat ミニプログラムのネイティブ コンポーネントであるカメラ、キャンバス、入力 (フォーカス...

div タグ内の要素の margin-top が無効である場合の解決策

タイトル通りです。その質問は非常に奇妙です。要素の親タグはdivで、幅や高さなどの属性は設定されてい...

Idea は、Web プロジェクトを開始するように Tomcat を設定します。グラフィック チュートリアル

tomcatの設定1. 実行構成をクリック 2. tomcat localを選択 3. tomcat...

CSS3 でのシンプルな LED デジタル時計の実装方法

これは多くの人がやったことがあるはずです。ただうずうずして書きたかったので、時間をかけていじってダー...