スケーラブルな列の完全な例を実現するための Ant 設計 Vue テーブル

スケーラブルな列の完全な例を実現するための Ant 設計 Vue テーブル

ant-design-vue テーブルのスケーラブルな列の問題に対する完璧なソリューション。固定列とマルチレベル ヘッダーでスケーラブルな列を実現します。

公式サイトに例が載っていたので、これは簡単に使えるだろうと思いました。しかし、公式サイトをあまり信用することはできません。公式サイトでは最も基本的なものしか提供されておらず、私たちの通常の使用シナリオは、固定列、固定ヘッダー、組み込みチェックボックス列、マルチレベルヘッダーなど、はるかに複雑な場合が多いです。こうした状況に対応するには、独自のものを開発する必要があることがよくあります。

1. まず、蒋介石の公式例を真似したのですが、引きずり出すことができませんでした。

公式のものと比較したところ、CSSが異なっていたため、最初の変更を加えました。スタイルのインラインスタイルには独自のtranslate属性があるため、right: 0を直接削除し、left -5のみにしました。高さを100%に設定しました。

.resize-table-th {
    位置: 相対的;
    .table-ドラッグ可能なハンドル {
      高さ: 100% !重要;
      下部: 0;
      左: -5px !重要;
      カーソル: col-resize;
      タッチアクション: なし;
      位置: 絶対;
    }
  }

2. 今回は、ドラッグするたびに translate 属性がリアルタイムで変化しますが、セルは広くなったり移動したりしないことがわかります。

そこで、要素を再度確認したところ、 th の幅は変化していましたが、 colGroup の width 属性は変化していませんでした。そこで、対応する colGroup 子要素 col を探し始めました。ついにそれを見つけたので、ドラッグしながら colGroup の col の width 属性を変更しました。こうすることで、変更を追跡できます。

3. 次に、列とヘッダーが固定されている場合にストレッチするとバグが発生することがわかりました。

コードを見ると、固定列や固定ヘッダーの場合、thead と tbody は実際には別のテーブルにあることがわかりました。このとき、col を測定して幅を変更するには、すべての colGroups を見つける必要があります。これは固定ヘッダーの伸縮を処理します。ただし、固定列の場合には、CSS を別途設定し、table-fixed-left を見つけて幅をリセットする必要があります。

ここにコードがあります

現在の th に従って、どの子ノード th が親要素であるかを判断し、それが colGroup のどの col ノードに対応するかを決定します。

定数 loopDom = ss => {
  ss.previousSibling !== null の場合 {
    thDomIndex++;
    loopDom(ss.previousSibling);
  }
};

固定列の幅をリセットします(左フロートのみ処理します)

関数 resetFixedColumns(幅) {
  const fixedHead = document.querySelector(".ant-table-fixed-left .ant-table-header");
  const fixedBody = document.querySelector(".ant-table-fixed-left .ant-table-body-outer .ant-table-fixed");
  if (固定ヘッド) {
    fixedHead.style.width = 幅 + "px";
    fixedBody.style.width = 幅 + "px";
  }
}

複数レベルのヘッダー拡張列の問題を解決する

配列を再帰的に走査して幅を取得する

getDraggingMap(tbCols、ドラッグマップ) {
      tbCols.forEach(列 => {
        if (col.children) {
          this.getDraggingMap(col.children, draggingMap);
        } それ以外 {
          const key = col.dataIndex || col.key; //テーブルデータにはこれらの 2 つの属性が必要です draggingMap[key] = col.width || 0;
        }
      });
    },

配列を再帰的に走査し、現在の列を取得します(この再帰は本当に面倒です。再帰の書き方についてどう感じているかはわかりません)

// マルチレベルヘッダーの処理 getRenderCoL(key, tbCols) {
      結果 = "" とします。
      this._.forEach(tbCols, 項目 => {
        if (item.children) {
          結果 = this.getRenderCoL(キー、item.children);
          !結果を返します。
        } それ以外 {
          const k = item.dataIndex || item.key;
          if (k === キー) {
            結果 = アイテム;
            false を返します。
          }
        }
      });
      結果を返します。
    }

配列を再帰的にトラバースして、マルチレベルヘッダー操作列のインデックスを取得します(再帰も耐えられません。最初は最後のレンターンが欠落しており、間違った実行が続きます。再帰のシャドウ領域は無限です)

 定数 loopDom = (cols, col) => {
          タグを true にします。
          this._.forEach(cols, co => {
            co.dataIndex == col.dataIndexの場合{
              thDomIndex++;
              タグ = false;
              戻りタグ;
            }
            if (co.children) {
              タグ = loopDom(co.children, col);
              戻りタグ;
            } それ以外 {
              thDomIndex++;
            }
          });
          戻りタグ;
        };

完全なコードはこちら

これは、テーブルメインファイルをミックスイン経由で導入するjsファイルです。テーブルは

:components="ドラッグ(列キー)"
//mixins/tableDragResize.js
「vue」からVueをインポートします。
「vue-draggable-resizable」から VueDraggableResizable をインポートします。
Vue.component("vue-draggable-resizable", VueDraggableResizable);

エクスポートデフォルト{
  データ() {
    戻る {
      最大レベル: 1
    };
  },
  メソッド: {
    ドラッグ(列) {
      戻る {
        ヘッダー: {
          セル: this.initDrag(列)
        }
      };
    },
    /**
     * @param { テーブル列 } tbCols
     */
    initDrag(tbCols) {
      ドラッグマップを {} にします。
      this.getDraggingMap(tbCols, draggingMap, 1);
      draggingState を Vue.observable(draggingMap) にします。
      戻り値 (h, props, children) => {
        thDomIndex = 0 とします。
        const { キー、...restProps } = props;
        col = {} とします。
        // マルチレベル ヘッダーの処理 col = this.getRenderCoL(key, tbCols);
        列の幅が等しい場合
          //ここで、テーブル データには width 属性が必要です。そうでない場合、次のドラッグは実行されません。 return <th {...restProps}>{children}</th>;
        }
        定数onDrag = x => {
          列の幅 = Math.max(x, 1);
          ドラッグ状態[キー] = col.width;
          ドメインインデックス = 0;
          loopDom(tbCols, col);
          チェックありの場合
            ドメインインデックス--;
          }
          colgroup を document.querySelectorAll("colgroup") とします。
          colgroup.forEach(要素 => {
            childCol を Element.children とします。
            childCol[thDomIndex]の場合、childCol[thDomIndex].style.width = col.width + "px";
          });
          this.resetFixedColumns(列の幅);
        };
        定数 loopDom = (cols, col) => {
          タグを true にします。
          this._.forEach(cols, co => {
            co.dataIndex == col.dataIndexの場合{
              thDomIndex++;
              タグ = false;
              戻りタグ;
            }
            if (co.children) {
              タグ = loopDom(co.children, col);
              戻りタグ;
            } それ以外 {
              thDomIndex++;
            }
          });
          戻りタグ;
        };
        定数onDragstop = () => {};

        戻る (
          <th {...restProps} width={draggingState[key]} class="resize-table-th" dataIndex={col.key}>
            {子供たち}
            <vue-ドラッグ可能-サイズ変更可能
              キー={col.dataIndex || col.key}
              クラス="テーブルドラッグ可能ハンドル"
              w={20}
              h = {this.getResizableHandler(col)}
              x={ドラッグ状態[キー]}
              100 は
              軸="x"
              ドラッグ可能={true}
              サイズ変更可能={false}
              onDragging={onDrag}
              onDragstop={onDragstop}
            </vue-ドラッグ可能-サイズ変更可能>
          </th>
        );
      };
    },
    getResizableHandler(col) {
      // baseH = thDom.getBoundingClientRect().height; とします。
      size を this.cellsize とします。this.cellsize : this.attrBute.cellsize;
      baseH を size == "middle" ? 47 とします : size == "small" ? 39 : 55;
      col.isEndNode の場合、baseH * col.nodeLevel を返します。
      そうでない場合 (col.leafNode && col.nodeLevel < this.maxLevel) {
        baseH * this.maxLevel を返します。
      } それ以外の場合は baseH を返します。
    },
    固定列幅をリセットする(幅)
      const fixedHead = document.querySelector(".ant-table-fixed-left .ant-table-header");
      const fixedBody = document.querySelector(".ant-table-fixed-left .ant-table-body-outer .ant-table-fixed");
      if (固定ヘッド) {
        fixedHead.style.width = 幅 + "px";
        fixedBody.style.width = 幅 + "px";
      }
    },
    getDraggingMap(tbCols、draggingMap、nodeLevel) {
      tbCols.forEach((列、インデックス) => {
        col.nodeLevel = ノードレベル;
        col.isEndNode = インデックス == tbCols.length - 1;
        this.maxLevel = Math.max(this.maxLevel、ノードレベル);
        if (col.children) {
          col.leafNode = false;
          this.getDraggingMap(col.children, draggingMap, nodeLevel + 1);
        } それ以外 {
          col.leafNode = true;
          const key = col.dataIndex || col.key; //テーブルデータにはこれらの 2 つの属性が必要です draggingMap[key] = col.width || 0;
        }
      });
    },
    getRenderCoL(キー、tbCols) {
      結果 = "" とします。
      this._.forEach(tbCols, 項目 => {
        if (item.children) {
          結果 = this.getRenderCoL(キー、item.children);
          !結果を返します。
        } それ以外 {
          const k = item.dataIndex || item.key;
          if (k === キー) {
            結果 = アイテム;
            false を返します。
          }
        }
      });
      結果を返します。
    }
  }
};

追記 マルチレベルテーブルヘッダーの拡張列に対する完璧なソリューション 元のgetDraggingMapメソッドを変更し、nodeLevelレベルを追加します。isEndNodeはカバーレベルの下の最後のノードであり、this.maxLevelは最大レベルを記録します

getDraggingMap(tbCols、draggingMap、nodeLevel) {
tbCols.forEach((列、インデックス) => {
col.nodeLevel = ノードレベル;
col.isEndNode = インデックス == tbCols.length - 1;
this.maxLevel = Math.max(this.maxLevel、ノードレベル);
if (col.children) {
col.leafNode = false;
this.getDraggingMap(col.children, draggingMap, nodeLevel + 1);
} それ以外 {
col.leafNode = true;
const key = col.dataIndex || col.key; //テーブルデータにはこれらの 2 つの属性が必要です draggingMap[key] = col.width || 0;
}
});
},

テーブルドラッグハンドルの高さを処理するメソッドを追加します

画像を表示

ここに画像の説明を挿入

ドラッグ可能な領域は赤い領域です。この効果を実現するには、次の処理が必要です。

まず、CSS の高さを削除します: 100%;
次にレンダリング時にコンポーネントの高さを次のように設定します。

h = {this.getResizableHandler(col)}

サイズはテーブルのサイズです

getResizableHandler(col) {
      // baseH = thDom.getBoundingClientRect().height; とします。
      size を this.cellsize とします。this.cellsize : this.attrBute.cellsize;
      baseH を size == "middle" ? 47 とします : size == "small" ? 39 : 55;
      col.isEndNode の場合、baseH * col.nodeLevel を返します。
      そうでない場合 (col.leafNode && col.nodeLevel < this.maxLevel) {
        baseH * this.maxLevel を返します。
      } それ以外の場合は baseH を返します。
    },

終わり

上記は、スケーラブルな列を実現するための ant design vue table の詳細です。ant design vue table scalable columns の詳細については、123WORDPRESS.COM の他の関連記事に注目してください。

以下もご興味があるかもしれません:
  • vue パブリック リスト選択コンポーネント、Vant-UI スタイルの参照
  • Ant Design Vue テーブル列の超長い表示...およびプロンプトの例の追加
  • Vue+vant が商品リストの一括カウントダウン機能を実現

<<:  Centos7 に yum 経由で MySQL をインストールする方法

>>:  Apache Tika を使用してファイルが破損しているかどうかを検出する方法

推薦する

MySQL マスタースレーブ構成の学習ノート

● 新しいプロジェクトのセキュリティを確保するためにクラウド データを購入する予定でした。 Alib...

VSCode の JS フォーマットでセミコロンを自動的に追加または削除する方法について

導入js コード文の末尾にセミコロンを追加しても追加しなくても問題ありません。一般的に、チームで開発...

Vue 学習 - VueRouter ルーティングの基礎

目次1. Vueルーター1. 説明2. 選択したルートのレンダリング: 3. 基本的な動作原理2. ...

Tomcat が応答データグラムを書き戻すタイミングの詳細な分析

疑問が生じるこの質問は、ファイルのダウンロードを記述しているときに発生しました。HttpServle...

Vue の下部ナビゲーション バー TabBar を実装するための非常に詳細なチュートリアル

目次プロジェクト紹介:プロジェクトディレクトリ: TabBar 効果のプレビュー: TabBar 実...

Linux のさまざまなロックメカニズムの使用方法と違いについて詳しく説明します

序文:この知識を理解する必要がある人は、すでにプロセス間通信とスレッド間通信の基本的な理解を持ってい...

ページコードの変更の効率を向上させ、HTML言語のコア知識を習得します。

ウェブサイトを構築するとき、HTML 言語は重要ではないと思われるかもしれませんが、実際には、基本的...

Angular CLI リリース パスの構成項目の簡単な分析

序文プロジェクトのリリースでは、常に特定の状況に応じたパッケージ化が必要です。Angular CLI...

Linux には make コマンドがありません (make: *** ターゲットが指定されておらず、makefile または make コマンドのインストール方法が見つかりません)

知らせ! ! !この状況は、実際には仮想マシンのインストール中に回避できます。次回仮想マシンをテスト...

UbuntuにCMakeをインストールするいくつかの方法の詳細な説明

CMakeをインストール sudo apt をインストール cmake この方法はインストールが簡単...

Docker+Jenkins+Gitlab+Djangoアプリケーションデプロイ実践の詳細な説明

1. 背景インターネット アプリケーションの急速な更新と反復という状況では、従来の手作業や単純なスク...

MySQL の Docker インストールと設定手順

目次序文環境インストールMySQLコンテナを作成して起動する思い出させるMySQLコンテナコマンドを...

「いいね!」文がインデックスに登録されないのはなぜですか?

序文この記事は、最も人気のある言語で最も退屈な基礎知識を説明することを目的としていますこのトピックは...

vue3とvue2の利点の比較

目次利点1: diffアルゴリズムの最適化利点2: ホイスト静的静的リフティング利点3: cache...

Vueのウォッチリスナーの使い方を説明する記事

目次リスナーウォッチ形式リスナーを設定します。要約するリスナーウォッチ関数名は、リッスンする要素の名...