vueはel-tableの列幅の適応を完璧に実現します

vueはel-tableの列幅の適応を完璧に実現します

背景

Element UI は、PC で人気の Vue.js UI フレームワークです。そのコンポーネント ライブラリは、基本的にほとんどの一般的なビジネス ニーズを満たすことができます。しかし、場合によっては、コンポーネント自体では満たせない、高度にカスタマイズされた要件が存在することがあります。最近、プロジェクトでこれに遭遇しました。

多くのページではテーブル コンポーネント el-table が必要です。 el-table-column に幅が指定されていない場合は、デフォルトで残りの列に均等に分散されます。列数が多い場合、el-table の幅がコンテナーに制限されると、セル内のコンテンツが折り返されます。行の折り返しを強制しません。コンテンツはセル内でスクロールするか、オーバーフローするか、切り捨てられます。

製品の望ましい効果は、コンテンツが 1 行に表示され、列の間隔が一定で、テーブルがコンテナーを超えて水平スクロールを可能にすることです。 el-table-column は固定幅の設定をサポートしており、コンテンツの幅が予測可能な場合にこの要件を満たすことができます。問題は、列の幅をコンテンツの幅に合わせて動的に調整する方法です。公式ドキュメントにはそのようなオプションは見つかりませんでした。おそらく、コンポーネント自体がサポートしていないためでしょう。

技術的ソリューション

そこで、コンテンツの幅を動的に計算するソリューションを考えました。このアイデアについてはオンラインで言及している人もいますが、そのアプローチは、コンテンツ内の文字数に基づいて幅を計算するというものです。このアプローチにはいくつかの制限があります。

  • コンテンツはテキストである必要があります
  • 文字によって幅が異なり、決済結果が十分に正確ではない
  • レンダリング前にデータを操作する必要があり、分離には役立たない

私は別のアイデアを採用しました。それは、実際にレンダリングされた DOM 要素の幅に基づいてコンテンツの幅を動的に計算することで、上記の 3 つの問題を解決できるというものです。

具体的にはどうすればいいのでしょうか?レンダリングされた DOM 要素を見ると、el-table のヘッダーとコンテンツはそれぞれネイティブ テーブルを使用し、各列の幅は colgroup によって設定されていることがわかります。ここから始めましょう。col の name 属性値は、対応する td の class 値と一致しています。このようにして、対応する列のすべてのセルをトラバースし、幅が最大のセルを見つけ、そのコンテンツ幅に余白を加えたものを列の幅として使用できます。

具体的な実装

コンテンツの幅を計算するには?これは比較的重要なステップです。レンダリング後、各セルには .cell クラスがあり、white-space: nowrap; overflow: auto; で改行を許可しないように設定されています。制限を超えた場合はコンテンツをスクロールでき、実際のコンテンツの幅を計算するために display: inline-block; が設定されています。このように、最終的な幅は .cell 要素の scrollWidth プロパティを通じて取得できます。

関数adjustColumnWidth(テーブル) {
  const colgroup = table.querySelector("colgroup");
  const colDefs = [...colgroup.querySelectorAll("col")];
  colDefs.forEach((col) => {
    const clsName = col.getAttribute("名前");
    定数セル = [
      ...table.querySelectorAll(`td.${clsName}`)、
      ...table.querySelectorAll(`th.${clsName}`)、
    ];
    // "leave-alone"クラスの列を無視する if (cells[0]?.classList?.contains?.("leave-alone")) {
      戻る;
    }
    定数widthList = cells.map((el) => {
      el.querySelector(".cell")?.scrollWidth || 0 を返します。
    });
    const max = Math.max(...widthList);
    定数パディング = 32;
    table.querySelectorAll(`col[name=${clsName}]`).forEach((el) => {
      el.setAttribute("幅", 最大値 + パディング);
    });
  });
}

途中の探索プロセスはかなり面倒ですが、最終的なコード実装は非常に簡潔です。列幅の計算はいつ実行されますか?当然、コンポーネントのレンダリングが完了した後です。再利用を容易にするために、Vue カスタム ディレクティブ アプローチを採用しました。

Vue.directive("fit-columns", {
  アップデート() {}、
  バインド() {},
  挿入(el) {
    タイムアウトを設定する(() => {
      列幅を調整します(el);
    }, 300);
  },
  コンポーネントが更新されました(el) {
    el.classList.add("r-table");
    タイムアウトを設定する(() => {
      列幅を調整します(el);
    }, 300);
  },
  アンバインド() {},
});

さらに、v-fit-columns という Vue プラグインをカプセル化しました。これは npm リポジトリに公開されており、直接インストールして使用できます。
インストール:

npm をインストール v-fit-columns --save

輸入:

'vue' から Vue をインポートします。
'v-fit-columns' からプラグインをインポートします。
Vue.use(プラグイン);

使用:

<el-table v-fit-columns>
  <el-table-column label="No." type="index" class-name="leave-alone"></el-table-column>
  <el-table-column label="名前" prop="名前"></el-table-column>
  <el-table-column label="年齢" prop="年齢"></el-table-column>
</el-table>

ソースコード リポジトリはこちらです: https://github.com/kaysonli/v-fit-columns。ぜひコメントやスターをお願いします!

要約する

このソリューションは、ある意味ハックであり、要件を満たすことのみに関心があります。レンダリング後にわずかなフラッシュが発生するなど、他の側面でいくつかの欠陥がある可能性があります (幅を再調整する必要があり、リフローが発生するため)。しかし、最終的な効果から判断すると、かなり満足のいくものです。

上記は、vue の el-table 列幅適応の完璧な実装の詳細な内容です。vue の el-table 列幅適応の実装の詳細については、123WORDPRESS.COM の他の関連記事に注目してください。

以下もご興味があるかもしれません:
  • Vueはel-tableを使用して円形カルーセルデータリストを実装します
  • VUE2.0+ElementUI2.0 テーブル el-table loop 動的列レンダリングの書き方を詳しく解説
  • vue+Element のテーブルは編集可能です (ドロップダウン ボックスを選択)
  • Vueはel-tableを使用してループし、テーブルを生成します。

<<:  Linuxサーバーのファイアウォールを変更してポートへのリモートアクセスを許可する方法

>>:  Windows 10 + mysql 8.0.11 zipインストールチュートリアルの詳細

推薦する

JDBC 探索 SQLException 分析

1. SQLExceptionの概要JDBC を使用してデータ ソース (この記事のデータ ソースは...

HTML スペースコードの簡単な分析

HTML についてどれくらい知っていますか? 現在、基本的な HTML コードを学習している場合は、...

ボタンに醜い灰色の枠線が付いています。これを削除するにはどうすればよいですか?

ダイアログをクロージャで使用し、右上隅の向こう側に閉じるボタンがあるダイアログを描画しました。ボタン...

Vueシングルページアプリケーションの事前レンダリング方法の例

目次序文vue-cli 2.0 バージョンvue-cli 3.0 バージョン要約する序文vue-cl...

Vue での Vue.prototype の使用に関する詳細な説明

目次1. 基本的な例2. インスタンスプロトタイプのスコープを設定する3. グローバル変数の登録と使...

MySQLの指定順序ソートクエリについての簡単な説明

最近、空港や駅でフライト情報を表示するものと似た大型スクリーンディスプレイのプロジェクトに取り組んで...

CSS と HTML とフロントエンド テクノロジーのレイヤー図

フロントエンドテクノロジー層 (写真は少し極端ですが、参考までに) Javascript と DOM...

ネイティブJSを使用した遅延読み込みlazyLoadの3つの方法の概要

目次序文方法1: 高コントラスト方法2: getBoundingClientRect() APIを使...

JavaScript カウントダウン プロンプト ボックス

この記事の例では、カウントダウンプロンプトボックスを実装するためのJavaScriptの具体的なコー...

MySQL truncate table ステートメントの使用

Truncate table ステートメントは、テーブル内のすべてのデータを削除/切り捨てるために使...

MySQL リンクを表示し、異常なリンクを削除する方法

序文:データベースの運用や保守の際には、リンクの総数がいくつあるか、アクティブなリンクがいくつあるか...

Ubuntu 18.04 に Nvidia グラフィック カード ドライバーをインストールするチュートリアル (画像とテキスト付き)

0. 事前準備BIOS でセキュア ブートを無効にします。無効にしないと、サードパーティ ソースを...

Docker イメージのインポートとエクスポートのコード例

Dockerイメージのインポートとエクスポートこの記事では、移行、バックアップ、アップグレードなどの...

HTML スクロールバーのテキストエリア属性の設定

1.オーバーフローコンテンツのオーバーフロー設定(設定されたオブジェクトにスクロールバーを表示するか...

Vue で v-if と v-for を一緒に使用することが推奨されない理由の詳細な説明

この記事では主に、v-if と v-for を一緒に使用することが推奨されない理由を紹介します。詳細...