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

推薦する

Gitコミットログの変更方法のまとめ

ケース1: 最後の提出とプッシュなし次のコマンドを実行します。 git コミット --amend g...

モバイルデバイス Web 開発における HTML ヘッドの書き方

コードをコピーコードは次のとおりです。 <ヘッド> <meta http-equi...

VUE+CanvasはシンプルなGobangゲームの全プロセスを実現します

序文レイアウトの点では、Gobang はランダムな動きを目的とするゲームよりも実装がはるかに簡単で、...

ウェブデザインとは何か

<br />元の記事: http://www.alistapart.com/articl...

JavaScript を使用して userAgent を通じていくつかの一般的なブラウザを判別する方法

序文通常、h5 ページを作成するときは、WeChat、QQ、Weibo などのエコシステム内でトラフ...

MySQLデータベースでコマンドを自動補完する3つの方法

注意: 3 番目の方法は XSell でのみ使用され、finalsell では使用できません。方法1...

Vueエンジニアがカプセル化しなければならない埋め込み命令の知識のまとめ

目次序文指導の基本フック機能フック関数のパラメータ文章使い方とアイデア成し遂げる汎用性を高める要約す...

反応ループデータの実装(リスト)

まず、バックグラウンドから来るデータをシミュレートしてみましょう。ここでは、コードをわかりやすくする...

MySQL における一般的なランキングの問題をいくつかまとめます

序文:一部のアプリケーション シナリオでは、成績や年齢によるランキングなど、ランキングの問題が発生す...

Linuxでディスク使用量を確認する方法

1. dfコマンドを使用してディスク全体の使用量を表示します。 df コマンドは、ハードディスクのマ...

Vue でのキープアライブコンポーネントの使用例

問題の説明(キープアライブとは何か)キープアライブ 名前の通り、アクティブな状態を維持します。誰が活...

Selenium+testng を使用して Docker で Web 自動化を実現する方法

序文長い間さまざまな資料を読んで、ついに selenium+testng のパラメータ化の問題を解決...

MySQLインスタンスを安全にシャットダウンする方法

この記事では、mysqld プロセスをシャットダウンするプロセスと、MySQL インスタンスを安全か...

Linux システムに Zookeeper サービスをインストールする方法

1. /usr/local/services/zookeeper フォルダを作成します。 mkdir...