【Angular】encapsulationって何?
Angularのコンポーネントに指定できるencapsulationについて調べました。
@Component({
selector: 'test',
template: `
<div class="test">Test!</div>
`,
styles: [`
:host {
.test {
color: red;
}
}
`],
// これ
encapsulation: ViewEncapsulation.Emulated
})
class TestComponent {
}
encapsulationは、コンポーネントに紐づくテンプレートとCSSの隠蔽の設定を行うもの
ViewEncapsulationはenumになっていて、ざっくり以下のような違いがあります。
| enumメンバー | 説明 |
|---|---|
| Emulated | デフォルト。AngularがShadow DOMをエミュレートし、テンプレートやCSSを隠蔽する。 |
| Native | Deprecatedになっている。かわりにShadowDomを推奨 |
| None | テンプレートやCSSの隠蔽を行わない。書いたものはグローバルスタイルに追加される。 |
| ShadowDom | Shadow DOMを使用し、テンプレートやCSSを隠蔽する |
Nativeを除く各要素について詳細に見てみました。
StackBlitzにコードを置いてあります
ViewEncapsulation.Emulated
デフォルトです。Shadow DOMの動作をエミュレートして、テンプレートやCSSをコンポーネント内に隠蔽します。
デモ:https://angular-ivy-mt4a7t.stackblitz.io/emulated
肝となるのは.test[_ngcontent-lyr-c47]の部分でしょうか。EmulatedTest1Component配下の要素には_ngcontent-lyr-c47という属性が自動的につけられ、それによりCSSの適用をコンポーネント内に限定することができています。詳しくはこちら:https://angular.jp/guide/component-styles#生成されたcssの検査
(デフォルトの振る舞いがこのように実現されているんだなぁと勉強になります。)
ViewEncapsulation.None
「テンプレートやCSSの隠蔽を行わない」というのを掘り下げると、例えばコンポーネントをあるページに配置した場合、そのページのすべてのコンポーネントにスタイルが適用されるということです。
デモ:https://angular-ivy-mt4a7t.stackblitz.io/none
NoneTest1ComponentでViewEncapsulation.Noneを指定しているので、none-test1.component.cssで指定した.testクラスのCSS(背景色を赤にする)がNoneComponentやNoneTest2Componentにも適用されてしまっているのがわかります。
Chrome DevToolsを見てみると、Emulatedの場合と違いCSS指定が単なる.testに対してになっているのでこのような挙動になるのだと理解できます。
ViewEncapsulation.Noneの使い所はいまいちイメージが湧きませんでしたが、使用するなら意図しないスタイルが効いてしまわないよう注意を払わなければいけません。
ViewEncapsulation.ShadowDom
CSSの隠蔽においてEmulatedのようなAngularの仕組みではなく、ブラウザのネイティブShadow DOMを利用するということです。
Shadow DOMについては深堀するのはやめておきますが、実際に挙動は見てみたいと思います。
デモ:https://angular-ivy-mt4a7t.stackblitz.io/shadow-dom
ViewEncapsulation.ShadowDomを指定したShadowDomTest1ComponentにShadowRootが追加されています。
Discussion