Element-ui レイアウト (行と列コンポーネント) の実装

Element-ui レイアウト (行と列コンポーネント) の実装

実際の開発でレイアウトに遭遇したときは、Layout を使用します。このレイアウトは、いくつかのパラメータが設定されている限り、優れたレイアウト効果を実現でき、レスポンシブにもなります。具体的にはどのように実装されるのでしょうか。Element-UI のソース コードを分析して、詳細を確認してみましょう。

基本的な手順と使用方法

Element-UI のレイアウトは 24 個の基本列に基づいており、レイアウトをすばやく簡単に作成できます。組み合わせ次第で、非常に美しいレスポンシブレイアウトを素早く生成できます。具体的な使い方は以下のとおりです。

<el-行>
  <el-col :span="24"><div class="grid-content bg-purple-dark"></div></el-col>
</el-row>

上記のサンプル コードから、Row コンポーネントは主に、行列間の間隔や配置など、各行列のレイアウトを作成するために使用されていることがわかります。 Col は、長さ、オフセットなどを含む各列を作成します。各列を自由に組み合わせて、レスポンシブな効果を実現できます。

行コンポーネントの分析

レンダリング機能

Vue でコンポーネントを記述するには、テンプレート テンプレートを使用するだけでなく、レンダリング関数を直接使用してコンポーネントを記述できる場合もあることは誰もが知っています。テンプレートは最終的にレンダリング関数にコンパイルされるためです。
なぜレンダリング機能があるのですか?たとえば、現在、次のような要件があります。動的レベルに応じて h1 から h6 までのフォント サイズでタイトルを生成する場合、テンプレートを使用して実装すると、ページ内に次のような疑似コードが多数含まれる可能性があります。

<テンプレート>
   <h1 v-if="レベル === 1">
    <スロット></スロット>
  </h1>
  <h2 v-else-if="レベル === 2">
    <スロット></スロット>
  </h2>
  <h3 v-else-if="レベル === 3">
    <スロット></スロット>
  </h3>
  <h4 v-else-if="レベル === 4">
    <スロット></スロット>
  </h4>
  <h5 v-else-if="レベル === 5">
    <スロット></スロット>
  </h5>
  <h6 v-else-if="レベル === 6">
    <スロット></スロット>
  </h6>
</テンプレート>

しかし、レンダリング関数を使用すると、比較的簡単になります。

Vue.component('アンカー付き見出し', {
  レンダリング: 関数 (createElement) {
    要素の作成を返す(
      'h' + this.level, // タグ名 this.$slots.default // 子ノード配列)
  },
  小道具: {
    レベル:
      タイプ: 数値、
      必須: true
    }
  }
})

ここには別のコード最適化ポイントがあります。 this.$slots.default はスロットの内容を格納し、何度も書き込む必要はありません。

ソースコード分析

Row コンポーネントのソース コードは比較的シンプルです。tag プロパティを使用してレンダリング タグを指定できるため、コンポーネントは render 関数を使用して直接記述されます。レンダリング関数は次のとおりです。

レンダリング(h) {
    h(this.tag, { を返す
      クラス: [
        「エル行」、
        this.justify !== 'start' ? `is-justify-${this.justify}` : '',
        this.align !== 'top' ? `is-align-${this.align}` : '',
        { 'el-row--flex': this.type === 'flex' }
      ]、
      スタイル: this.style
    }, this.$slots.default);
  }

上記のソースコードから、Row は主にクラス名を制御してコンテンツのレイアウトを制御していることがわかります。行内の列間のギャップの数を制御するガター プロパティがあります。 gutter=20 に設定すると、各列項目の左右の間隔は 10px になり、最初の列項目と最後の列項目の間に左右の間隔ができてしまうという問題が発生します。では、最初と最後の間の 10 ピクセルのギャップを削除するにはどうすればよいでしょうか? Row の解決策は、行を各側で -10px オフセットすることです。そのため、計算プロパティを使用してスタイルを設定します。

計算: {
    スタイル() {
      定数ret = {};
      if (this.gutter) {
        ret.marginLeft = `-${this.gutter / 2}px`;
        ret.marginRight = ret.marginLeft;
      }
      ret を返します。
    }
  },

Col成分の分析

コンポーネント分析

Col は主に各列の長さとオフセットを設定するために使用されます。主な属性は span と offset です。このコンポーネントも render 関数を使用して記述されています。まず、span と offset を使用して列を制御する方法を見てみましょう。ソース コードは次のとおりです。

レンダリング(h) {
    classList = [] とします。
    スタイルを {} にします。
    ...

    ['span', 'offset', 'pull', 'push'].forEach(prop => {
      if (this[prop] || this[prop] === 0) {
        クラスリスト.push(
          プロパティ !== 'span'
            ? `el-col-${prop}-${this[prop]}`
            : `el-col-${this[prop]}`
        );
      }
    });

    ...

    h(this.tag, { を返す
      クラス: ['el-col', クラスリスト],
      スタイル
    }, this.$slots.default);
  }

このことから、col の列幅は異なるクラス名によって制御されていることがわかります。対応する .scss ファイルを見つけ、さまざまなグリッドの幅を計算するために sass@for ループ ステートメントが使用されていることがわかりました。

@for $i は 0 から 24 まで {
  .el-col-#{$i} {
    幅: (1 / 24 * $i * 100) * 1%;
  }

  .el-col-offset-#{$i} {
    左マージン: (1 / 24 * $i * 100) * 1%;
  }

  .el-col-pull-#{$i} {
    位置: 相対的;
    右: (1 / 24 * $i * 100) * 1%;
  }

  .el-col-push-#{$i} {
    位置: 相対的;
    残り: (1 / 24 * $i * 100) * 1%;
  }
}

同様に、オフセットでも同じロジックが使用されます。このように、異なるスパンとオフセットに応じて、さまざまなスタイルのレイアウトを組み合わせることができます。その背後にあるロジックはとてもシンプルだと思いませんか?別の質問について考えてみましょう。同一の列幅間隔のグループを制御したい場合、それらを 1 つずつ設定する必要がありますか?答えは「いいえ」です。前述の Row コンポーネントの gutter プロパティを使用して、統一された設定を行うことができます。それで、これはどのように達成されるのでしょうか?ソースコードは次のとおりです。

 計算: {
    ガター() {
      親を this.$parent とします。
      (親 && parent.$options.componentName !== 'ElRow') {
        親 = 親.$parent;
      }
      親を返します? parent.gutter: 0;
    }
  }

親コンポーネントを上方向にトラバースします。親コンポーネントのコンポーネント名が ElRow の場合、ガター値を取得し、コンポーネントの左マージンと右マージンに対応する値を設定します。

if (this.gutter) {
      style.paddingLeft = this.gutter / 2 + 'px';
      style.padding 右 = style.padding 左;
    }

このようにして、列幅を均一に設定するという問題を解決しました。

レスポンシブレイアウト

ここでは、CSS3 のメディア クエリを使用してレスポンシブ レイアウトを実行します。対応するサイズは xs、sm、md、lg、xl です。使用コードは次のとおりです。

<el-row :gutter="10">
  <el-col :xs="8" :sm="6" :md="4" :lg="3" :xl="1"><div class="grid-content bg-purple"></div></el-col>
  <el-col :xs="4" :sm="6" :md="8" :lg="9" :xl="11"><div class="grid-content bg-purple-light"></div></el-col>
  <el-col :xs="4" :sm="6" :md="8" :lg="9" :xl="11"><div class="grid-content bg-purple"></div></el-col>
  <el-col :xs="8" :sm="6" :md="4" :lg="3" :xl="1"><div class="grid-content bg-purple-light"></div></el-col>
</el-row>

説明: xs: <768px のレスポンシブ グリッド番号またはグリッド プロパティ オブジェクト、sm: ≥768px のレスポンシブ グリッド番号またはグリッド プロパティ オブジェクト、md: ≥992px のレスポンシブ グリッド番号またはグリッド プロパティ オブジェクト、lg: ≥1200px のレスポンシブ グリッド番号またはグリッド プロパティ オブジェクト、xl: ≥1920px のレスポンシブ グリッド番号またはグリッド プロパティ オブジェクト。

この背後にあるロジックは、異なる画面サイズに表示されるグリッドの数が異なり、画面の幅に応じて応答するということです。まず、さまざまなクラス バインディングを実行する方法を見てみましょう。

['xs', 'sm', 'md', 'lg', 'xl'].forEach(サイズ => {
      if (typeof this[size] === 'number') {
        classList.push(`el-col-${size}-${this[size]}`);
      } そうでない場合 (typeof this[size] === 'object') {
        props = this[サイズ]とします。
        Object.keys(props).forEach(prop => {
          クラスリスト.push(
            プロパティ !== 'span'
              ? `el-col-${size}-${prop}-${props[prop]}`
              : `el-col-${size}-${props[prop]}`
          );
        });
      }
    });

ここでは、xs などの属性にもオブジェクトを使用できます。したがって、オブジェクトを処理するロジックが存在します。上記の js 処理ロジックは比較的単純です。このメディアクエリのロジックを CSS がどのように処理するかを見てみましょう。
CSS を分析するときは、まず Sass の組み込みメソッド map-get という概念を理解します。 map-get($map,$key) の機能は、$key を通じて対応する値を取得することであり、これはマッピング関係として理解できます。存在しない場合、対応する CSS はコンパイルされません。例えば:

$ソーシャルカラー: (
    ドリブル: #ea4c89,
    フェイスブック: #3b5998,
    github: #171515、
    グーグル: #db4437,
    ツイッター: #55acee
);
.btn-ドリブル{
  色: map-get($social-colors,facebook);
}
// コンパイル後.btn-dribble {
  色: #3b5998;
}

2 番目は、文字列表現を返す Sass 組み込みメソッドの inspect(value) です。value は Sass 式です。例えば:

$--sm:768px !デフォルト;
$--md:992px !デフォルト;
$--lg:1200px !デフォルト;
$--xl:1920px !デフォルト;

$--ブレークポイント: (
  'xs' : (最大幅: $--sm - 1),
  'sm' : (最小幅: $--sm),
  'md' : (最小幅: $--md),
  'lg' : (最小幅: $--lg),
  'xl' : (最小幅: $--xl)
);
@mixin res($breakpoint){
  $クエリ:マップ取得($--ブレークポイント、$ブレークポイント)
  @if not $query {
    @error '`#{$breakpoint}` の値が見つかりません。正しいかどうか確認してください 
    `$breakpoints` マップで定義されています。';
  }
  @media #{inspect($query)}
   {
    @コンテンツ;
   }
}
。要素 {
  色: #000;
 
  @include res(sm) {
    色: #333;
  }
}
// コンパイルされた CSS

。要素 {
  色: #000;
}
@media (最小幅: 768px) {
  。要素 {
    色: #333;
  }
}

さて、これら 2 つの方法を十分に習得できたと思いますので、要素がどのように実装されるかを見てみましょう。
実際、上記の 2 番目の例ではすでに何かが述べられています。ソース コードを見てみましょう。

$--sm:768px !デフォルト;
$--md:992px !デフォルト;
$--lg:1200px !デフォルト;
$--xl:1920px !デフォルト;

$--ブレークポイント: (
  'xs' : (最大幅: $--sm - 1),
  'sm' : (最小幅: $--sm),
  'md' : (最小幅: $--md),
  'lg' : (最小幅: $--lg),
  'xl' : (最小幅: $--xl)
);
/* ブレークポイント
 -------------------------- */
@mixin res($key, $map: $--ブレークポイント) {
  // ループブレークポイントマップ、存在する場合は返す @if map-has-key($map, $key) {
    @media 画面のみと #{inspect(map-get($map, $key))} {
      @コンテンツ;
    }
  } @それ以外 {
    @warn "未定義のポイント: `#{$map}`";
  }
}
@include res(xs) {
  @for $i は 0 から 24 まで {
    .el-col-xs-#{$i} {
      幅: (1 / 24 * $i * 100) * 1%;
    }

    .el-col-xs-offset-#{$i} {
      左マージン: (1 / 24 * $i * 100) * 1%;
    }
  }
}
@include res(sm) {
  ...
}
@include res(md) {
  ...
}
@include res(lg) {
  ...
}
@include res(xl) {
  ...
}

このように、異なる画面サイズに異なる長さと間隔で表示します。このようにメディア クエリを記述するのは素晴らしいことではないでしょうか。

これで、Element-ui レイアウト (Row および Col コンポーネント) の実装に関するこの記事は終了です。より関連性の高い Element レイアウト コンテンツについては、123WORDPRESS.COM の以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • el-row列レイアウトの使用に関するElement-UIチュートリアル
  • Vue Element UI カスタム説明リストコンポーネント
  • 要素 el-row el-col レイアウト コンポーネントの詳細な説明

<<:  CSS (カスケーディング スタイル シート) の一般的な用語の概要

>>:  ブラウザのキャッシュを防ぐために、js または css の後に ?v= バージョン番号を追加します。

推薦する

Linux におけるシステム入出力管理の詳細な説明

システムの入力と出力の管理1. システムの入力と出力を理解するLinuxシステムでは、1は正しい出力...

Springboot+Vue-Cropperでアバターの切り取りとアップロードの効果を実現

アバターをアップロードするにはVue-Cropperコンポーネントを使用します。参考までに具体的な内...

データ構造 - ツリー (III): 多方向検索ツリー B ツリー、B+ ツリー

多方向探索ツリー完全二分木の高さ: O(log2N)、ここで2は対数完全なM方向探索木の高さ: O(...

自動検索提案機能のスタイルファイルを入力します: suggestion.css

コードをコピーコードは次のとおりです。 .sugLayerDiv{位置:相対; overflow:h...

優れたWebフォームデザイン事例20選

ソフィー・ハルダッククライドキー埠頭 37 東ソープボックス Rxバランス EEハーバー対比 SVN...

docker ベースの mariadb のインストール構成プロセスの分析

1. インストール dockerhub を通じてインストールする mariadb のバージョンを検索...

ハイパーリンクを開くターゲットのテスト

リンクのターゲット属性は、リンクが開く場所を決定します。その値は通常、_blank、_self、_p...

DockerでのinfluxDB分散時系列データベースのインストールと関連操作について簡単に説明します。

influxDB の紹介influxDB は分散型時系列データベースです。 cAdvisor はリ...

nginx を使用して正規表現で指定された URL リクエストを傍受する方法

nginx サーバーnginx は、静的ファイルの処理に非常に効率的な優れた Web サーバーです。...

MySql インデックス使用戦略の分析

MySql インデックスインデックスの利点1. 一意のインデックスまたは主キー インデックスを作成す...

見栄えの良い CSS カスタム スタイル (タイトル h1 h2 h3)

レンダリングBlog Gardenでよく使われるスタイル /*タイトル h1 h2 h3 スタイル*...

オンラインMySQLオプティマイザの誤判断によって発生した低速クエリイベントを記録する

序文:非常に遅いクエリとリクエストのタイムアウトのアラートを受け取りました。メトリックを通じて My...

Ubuntu 16.04.5LTS に SVN をインストールする手順

この記事では、UbuntuシステムでSVNを設定するプロセスを簡単に紹介します。ソースを更新sudo...

Nginx ロケーション設定のチュートリアル (ゼロから)

基礎位置の一致順序は、「最初に正規表現に一致し、次に共通表現に一致」です。実際のロケーションの一致順...

忘れられたボタンタグ

注:この記事は他の人によって翻訳されていますが、考えるべき点が多く、理解しにくい点もあると感じていま...