🤖

【Angular】encapsulationって何?

2020/09/19に公開

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にコードを置いてあります
https://angular-ivy-mt4a7t.stackblitz.io

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が追加されています。

参考

What is ViewEncapsulation in Angular? - DEV

Angular 日本語ドキュメンテーション - コンポーネントスタイル

Discussion