日常業務では、 Component を定義するときに、そのカプセル化を考慮する必要があります。つまり、このコンポーネントで定義されたスタイルがこのコンポーネントにのみ作用することを期待するか、それともグローバルに作用するかを考慮する必要があります。 Angular では、コンポーネントのスタイルをコンポーネントのホスト要素内にカプセル化して、アプリケーションの残りの部分に影響を与えないようにすることができます。コンポーネント デコレーターは、ビューのカプセル化をコンポーネントごとに適用する方法を制御するために使用できるカプセル化オプションを提供します。 [関連チュートリアルの推奨事項: "angular チュートリアル"]
Angular には、ViewEncapsulation.ShadowDom、ViewEncapsulation.Emulated、および ViewEncapsulation.None という 3 つのカプセル化モードがあります。
エクスポート列挙型 ViewEncapsulation { /** * 特定の属性を * コンポーネントのホスト要素と、提供されたすべての CSS セレクターに同じ属性を適用する * {@link Component#stylesstyles} または {@link Component#styleUrls styleUrls} 経由。 * * これはデフォルトのオプションです。 */ エミュレート = 0、 /** * いかなる種類の CSS スタイルのカプセル化も提供しません。つまり、提供されるすべてのスタイルが提供されます。 * {@link Component#stylesstyles} または {@link Component#styleUrls styleUrls} 経由が適用されます * ホスト コンポーネントに関係なく、アプリケーションの任意の HTML 要素に。 */ なし = 2、 /** * ブラウザーのネイティブ Shadow DOM API を使用して CSS スタイルをカプセル化します。つまり、 * カプセル化するために使用されるコンポーネントのホスト要素の ShadowRoot * すべてのコンポーネントのスタイル。 */ シャドウドム=3 ViewEncapsulation.Emulated
指定しない場合、値は CompilerOptions から取得されます。デフォルトのコンパイラ オプションは ViewEncapsulation.Emulated です。
ポリシーが ViewEncapsulation.Emulated に設定されており、コンポーネントでスタイルまたは styleUrls が指定されていない場合、自動的に ViewEncapsulation.None に切り替わります。
列挙型に 1 がない理由はわかりましたか?これについては後で詳しく説明します。
Angular での ShadowDom のカプセル化はさておき、まず ShadowDOM とは何かを見てみましょう。
シャドウ DOM を使用すると、非表示の DOM ツリーを通常の DOM ツリーに接続できます。このルート ノードの下には、通常の DOM 要素と同様に、任意の要素を指定できます。
ここで、理解する必要がある Shadow DOM 固有の用語がいくつかあります。
Shadow DOM は、子ノードの追加、プロパティの設定、ノードへの独自のスタイルの追加 (element.style プロパティなどによる)、または全体へのスタイルの追加など、通常の DOM と同じ方法で操作できます。 Shadow DOM (要素内にスタイルを追加するなど)。違いは、Shadow DOM 内の要素がその外部の要素 (:focus-within を除く) に影響を与えないことです。これにより、カプセル化が容易になります。
簡単な例を見てみましょう。
<!DOCTYPE html> <html> <頭> <meta charset="UTF-8"> <meta http-equiv="X-UA 互換" content="IE=edge"> <meta name="viewport" content="width=device-width、initial-scale=1.0"> <title>シャドウ DOM</title> <スタイル> スパン{ 色: 緑; } </スタイル> </head> <本文> <span>私はルートです</span> <div id="app"></div> <スクリプト> let app = document.querySelector('#app'); letshadow1 = app.attachShadow({ モード: 'open'}); let style1 = document.createElement('style'); style1.appendChild(document.createTextNode("span{color: red;}")); シャドウ1.appendChild(スタイル1); スパン1 = document.createElement('スパン'); span1.textContent = '私はスパンです。'; シャドウ1.appendChild(スパン1); </script> </body> </html>
上記の例では、グローバル スパン スタイルとshadowDOM のスパン スタイルが定義されています。これらは相互に影響を受けないことがわかります。
ShadowDOM とは何かを理解した後、Angular での ShadowDOM のカプセル化を見てみましょう。
Angular は、ブラウザーの組み込み Shadow DOM API を使用して、コンポーネントのビューを ShadowRoot (コンポーネントのホスト要素として機能します) でラップし、提供されたスタイルを分離した方法で適用します。 ViewEncapsulation.ShadowDom は、Shadow DOM のサポートが組み込まれているブラウザでのみ動作します。すべてのブラウザがこれをサポートしているわけではないため、ViewEncapsulation.Emulated が推奨されるデフォルトのモードです。
たとえば、次の例では、 ViewEncapsulation.ShadowDomを使用します。
@成分({ セレクター: 'ユーザー-子', templateUrl: 'UserChild.component.html', スタイル: [` h3{ 色: 赤; } `]、 カプセル化: ViewEncapsulation.ShadowDom }) エクスポート クラス UserChildComponent は OnInit を実装します { ... }
実行中のページから、ユーザーと子コンポーネントが内部的に ShadowDOM にカプセル化されており、スタイルも内部にカプセル化されており、外部スタイルには影響を与えないことがわかります。
Angular は、コンポーネントの CSS セレクターを変更して、コンポーネントのビューにのみ適用され、アプリケーション内の他の要素に影響を与えないようにします (Shadow DOM の動作をエミュレートします)。
モック ビューのカプセル化を使用する場合、Angular はすべてのコンポーネント スタイルを前処理して、コンポーネントのビューにのみ適用されるようにします。実行中の Angular アプリケーションの DOM では、モック ビューのカプセル化パターンを使用するコンポーネントを含む要素には、いくつかの追加属性が添付されています:
<hero-details _nghost-pmm-5> <h3 _ngcontent-pmm-5>ミスター・ファンタスティック</h3> <ヒーローチーム _ngcontent-pmm-5 _nghost-pmm-6> <h4 _ngcontent-pmm-6>チーム</h4> </ヒーローチーム> </hero-details>
このような属性は 2 つあります。
属性 | items_nghost は | |
---|---|---|
、コンポーネント ビューをラップする要素に追加されます。これは、ネイティブ Shadow DOM ラッパーの ShadowRoots になります | 。 | これは通常、コンポーネントのホスト要素の場合に当てはまります。 |
_ngcontent は | 、コンポーネント ビューの子要素に追加され、これらの属性は、要素をそれぞれのシミュレートされた ShadowRoot (_nghost 属性と一致するホスト要素) に一致させるために使用されます。 |
これらのプロパティの正確な値は、Angular のプライベート実装の詳細です。これらは自動的に生成されるため、アプリケーション コード内で参照しないでください。
これらは、DOM の一部に挿入される、生成されたコンポーネント スタイルをターゲットとしています:
[_nghost-pmm-5] { 表示: ブロック; 境界線: 1 ピクセルの黒一色。 } h4[_ngcontent-pmm-6] { 背景色: 白; ボーダー: 1px ソリッド #777;これらのスタイルは
、
各 CSS セレクターが適切な _nghost または _ngcontent 属性で拡張されるように後処理されます。これらの変更されたセレクターにより、スタイルが分離されたターゲットを絞った方法でコンポーネントのビューに適用されます。
<p>子供はうまくいきます!</p>
p{ 色: 緑; }
@成分({ セレクター: 'app-child', templateUrl: './child.component.html', styleUrls: ['./child.component.scss'], カプセル化: ViewEncapsulation.Emulated }) エクスポート クラス ChildComponent は OnInit {を実装します。 ... }
ViewEncapsulation.Emulated 設定の結果、Shadow DOM は存在しませんが、コンポーネントは Angular が提供するスタイル パッケージ化メカニズムを通じてカプセル化されるため、コンポーネントのスタイルは外部の影響を受けません。スタイルは依然としてドキュメント全体に適用されますが、Angular は p の [_ngcontent-oow-c11] セレクターを作成します。コンポーネントに定義したスタイルが Angular によって変更されていることがわかります。簡単に言うと、グローバル スタイルではありますが、自動セレクターにより他のコンポーネントのスタイルには影響しません。この属性を他の要素に手動で追加すると、スタイルもこの要素に適用されます。
Angular は、いかなる形式のビュー カプセル化も適用しません。つまり、コンポーネントに指定されたスタイルは実際にはグローバルに適用され、アプリケーション内に存在するすべての HTML 要素に影響を与える可能性があります。このパターンは、HTML 自体にスタイルを含める場合と本質的に同じです。
親:
<p #caption>親は機能します!{{count}}</p> <p #caption>最初の 1 つ: {{count}}</p> <span class="red-font">親</span> <app-child></app-child>
子:
<div style="border: 1px Solid green;"> <p>子供はうまくいきます!</p> <span class="red-font">子供</span> </div>
p{ 色: 緑; } .red-font { 色: 赤; }
@成分({ セレクター: 'app-child', templateUrl: './child.component.html', styleUrls: ['./child.component.scss'], カプセル化: ViewEncapsulation.None }) エクスポート クラス ChildComponent は OnInit {を実装します。 ... }
Angular2 では ViewEncapsulation.Native を使用します。
@成分({ ...、 カプセル化: ViewEncapsulation.Native }) エクスポートクラス UserComponent {
ViewEncapsulation.Native 設定により、ネイティブ Shadow DOM 機能が使用されます。 Angular は、ブラウザーでサポートされている Shadow DOM 形式に従ってコンポーネントをレンダリングします。実際、これは後の ViewEncapsulation.ShadowDom です。
Angular ビューのカプセル化の 3 つの方法とそれぞれの特徴を紹介しました。日常の作業では、特定のシナリオに応じてどのカプセル化方法を選択する必要があります。