スケーラブルな列の完全な例を実現するための 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 を使用してファイルが破損しているかどうかを検出する方法

推薦する

CentOS7環境にMySQL5.5データベースをインストールする

目次1. 現在のシステムにMySQLがインストールされているかどうかを確認する2. インストールされ...

Vue ユニットテストに関する予備調査

目次序文なぜユニットテストを導入するのですか?ユニットテストの概要テスト開発パターン1. テスト駆動...

OR キーワードを使用した MySql 複数条件クエリ ステートメント

前の記事では、And キーワードを使用した MySql の複数条件クエリ ステートメントを紹介しまし...

Django+vue 登録とログインのサンプルコード

登録するフロントエンドは、vue の axios を使用して値を渡し、取得したアカウントとパスワード...

MySQL のロングトランザクション例の詳細な説明

序文: 「MySQL 入門」シリーズの記事は終了しました。今後も引き続き MySQL に焦点を当て、...

MySQL の完全なデータベース バックアップ データを使用して単一のテーブル データを復元する方法

序文データベースをバックアップするときは、データベース全体のバックアップを使用します。ただし、何らか...

JavaScript に関する 6 つの奇妙で便利な点

目次1. 解体のヒント2. デジタルセパレーター3. try...catch...finally が...

Apache FlinkCEP でタイムアウトステータス監視を実装するための詳細な手順

CEP - 複合イベント処理。ご注文後、一定期間内にお支払いの確認が取れませんでした。タクシーの配...

MySQL GTID マスターとスレーブの不一致を修復するソリューション

目次解決策1: レプリカを再構築する前提条件アドバンテージ欠点手順マスター奴隷解決策2: データ修復...

ドロップダウンメニューを実現するためのHTML+CSS

1. ドロップダウンリストの例コードは次のとおりです。 <!doctypehtml> ...

MySQL が起動直後にシャットダウンする問題 (ibdata1 ファイルの破損が原因) に対する完璧な解決策

コンピュータ ルームのサーバー上の mysql がしばらく実行されていたのですが、突然、再起動しても...

WIN2008 サーバーのコマンド ラインを使用して IIS7 コンポーネントをインストールおよびアンインストールする方法

注意: .NET FrameWork はコア モードで実行できないため、コア インストール モードの...

Web デザイン体験: 5 つの優れた Web デザイン コンセプトの完全分析 (画像)

他の種類のデザインとは異なり、Web デザインは時代の発展とともに常に変化しています。したがって、W...

Web ページのデザインを学ぶときに習得すべきコードは何ですか?

この記事では、Web ページ制作を学ぶ過程で習得すべきテクニックの一部を詳しく紹介します。これらの内...

uniapp WeChatミニプログラムのグローバル共有を実装するためのサンプルコード

目次グローバル共有コンテンツファイルを作成するファイルをインポートしてグローバルに登録するページ共有...