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= バージョン番号を追加します。

推薦する

ウェブサイト製品設計の参考となるいくつかの原則

以下の分析は製品設計原則に関するものですが、そのほとんどはウェブサイト製品に基づいているため、ユーザ...

MySQL テーブル構造を Excel にエクスポートする方法

要件は次のとおりですテーブル構造、フィールドコメント情報、テーブル名などをエクスポートします。これは...

HTML でフォーム コントロールを無効にする 2 つの方法: readonly と disabled

Web ページを作成する過程では、フォームがよく使用されます。しかし、フォーム上のコントロールを変更...

Docker イメージに基づいて Go プロジェクトをデプロイする方法と手順

知識への依存Go クロスコンパイルの基礎Dockerの基礎Dockerfileカスタムイメージの基本...

フロントエンドネットワーク、JavaScriptの最適化、開発のヒントについて簡単に説明します。

1. ネットワークの最適化YSlowには23のルールがあります。これら数十のルールは、主に、不要な...

Centos7.4 サーバーへの Apache のインストールとインストール プロセス中に発生した問題の解決策

この記事では、CentOS 7.4 サーバーに Apache をインストールする方法と、インストール...

ドメイン名、ポート、IPに基づいてnginx仮想ホストを構築する

nginxでサポートされている仮想ホストには3つの種類があります1. ドメイン名ベースの仮想ホスティ...

Linux での MySQL 5.6.27 インストール チュートリアル

この記事では、LinuxでのMySQL 5.6.27のインストールチュートリアルを参考までに紹介しま...

MySQL の 10 進数データ型の小数点埋め込み問題の詳細な説明

序文開発プロセスでは、10 進データ型がよく使用されます。 MySQL では、小数点は正確なデータ型...

vue の v-bind を理解する

目次1. v-bindの主要ソースコードの分析1. v-bind属性はどこに均一に保存されるか: a...

MySQLインデックスの詳細

1. インデックスの原則インデックスは、列内の特定の値を持つ行をすばやく見つけるために使用されます。...

Nginx のリロード プロセスの背後にある真実を探る

本日の記事では、主にNginxのリロードプロセスについて紹介します。実は前回の記事では、nginx ...

MySQL における UNION と UNION ALL の基本的な使い方

データベースでは、UNION キーワードと UNION ALL キーワードの両方が 2 つの結果セッ...

MySQL サーバーの接続、切断、および cmd 操作

mysql コマンドを使用して MySQL サーバーに接続します。 MySQL サーバーが起動したら...