일상적인 작업에서 Component 를 정의할 때 캡슐화 를 고려해야 합니다. 즉, 이 구성 요소에 정의된 스타일이 이 구성 요소에만 작동할 것으로 예상합니까, 아니면 전역적으로 작동하기를 원합니까? Angular에서는 구성 요소의 스타일이 구성 요소의 호스트 요소 내에 캡슐화되어 애플리케이션의 나머지 부분에 영향을 주지 않습니다. 구성 요소 데코레이터는 구성 요소별로 뷰 캡슐화가 적용되는 방식을 제어하는 데 사용할 수 있는 캡슐화 옵션을 제공합니다. [관련 튜토리얼 권장 사항: "angular 튜토리얼"]
Angular에는 ViewEncapsulation.ShadowDom, ViewEncapsulation.Emulated 및 ViewEncapsulation.None의 세 가지 캡슐화 모드가 있습니다.
열거형 ViewEncapsulation 내보내기 { /** * 특정 속성을 추가하여 기본 Shadow DOM 캡슐화 동작을 에뮬레이트합니다. * 구성요소의 호스트 요소 및 제공된 모든 CSS 선택기에 동일한 속성 적용 * {@link Component#styles styles} 또는 {@link Component#styleUrls styleUrls}를 통해. * * 기본 옵션입니다. */ 에뮬레이트됨 = 0, /** * 어떤 종류의 CSS 스타일 캡슐화도 제공하지 않습니다. 즉, 제공된 모든 스타일이 * {@link Component#styles styles} 또는 {@link Component#styleUrls styleUrls}를 통해 적용 가능 * 호스트 구성 요소에 관계없이 응용 프로그램의 모든 HTML 요소에 적용됩니다. */ 없음 = 2, /** * 브라우저의 기본 Shadow DOM API를 사용하여 CSS 스타일을 캡슐화합니다. * 캡슐화하는 데 사용되는 구성 요소의 호스트 요소에 대한 ShadowRoot * 모든 구성 요소의 스타일. */ 섀도우돔=3 }
제공되지 않으면 CompilerOptions에서 값을 가져옵니다. 기본 컴파일러 옵션은 ViewEncapsulation.Emulated입니다.
정책이 ViewEncapsulation.Emulated로 설정되어 있고 구성 요소가 스타일이나 styleUrls를 지정하지 않으면 자동으로 ViewEncapsulation.None으로 전환됩니다.
열거형에 1이 없는 이유를 확인하셨나요 ? 이에 대해서는 나중에 자세히 설명합니다.
Angular의 ShadowDom 캡슐화는 제쳐두고 먼저 ShadowDOM이 무엇인지 살펴보겠습니다.
Shadow DOM을 사용하면 숨겨진 DOM 트리를 일반 DOM 트리에 연결할 수 있습니다. 이는 섀도우 루트 노드로 시작합니다. 이 루트 노드 아래에는 일반 DOM 요소와 마찬가지로 모든 요소가 포함될 수 있습니다.
여기에는 우리가 이해해야 할 몇 가지 Shadow DOM 관련 용어가 있습니다.
일반 DOM과 동일한 방식으로 Shadow DOM을 조작할 수 있습니다. 예를 들어 하위 노드를 추가하고, 속성을 설정하고, 노드에 자신만의 스타일을 추가하거나(예: element.style 속성을 통해) 전체 스타일에 스타일을 추가할 수 있습니다. Shadow DOM(예: 요소 내에 스타일 추가) 차이점은 Shadow DOM 내부 요소가 외부 요소에 영향을 미치지 않는다는 것입니다(:focus-within 제외). 이는 캡슐화를 용이하게 합니다.
간단한 예를 살펴보겠습니다.
<!DOCTYPE HTML> <html> <머리> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <title>섀도우 DOM</title> <스타일> 기간{ 색상: 녹색; } </style> </head> <본문> <span>나는 루트입니다</span> <div id="앱"></div> <스크립트> let app = document.querySelector('#app'); let Shadow1 = app.attachShadow({ 모드: '열기'}); let style1 = document.createElement('style'); style1.appendChild(document.createTextNode("span{color: red;}"))); Shadow1.appendChild(style1); let span1 = document.createElement('span'); span1.textContent = '저는 스팬입니다.'; Shadow1.appendChild(span1); </script> </body> </html>
위의 예에서는 전역 범위 스타일과 ShadowDOM의 범위 스타일이 서로 영향을 받지 않음을 알 수 있습니다.
ShadowDOM이 무엇인지 이해한 후 Angular에서 ShadowDOM을 캡슐화하는 방법을 살펴보겠습니다.
Angular는 브라우저에 내장된 Shadow DOM API를 사용하여 구성 요소의 뷰를 ShadowRoot(구성 요소의 호스트 요소 역할을 함)로 래핑하고 제공된 스타일을 격리된 방식으로 적용합니다. ViewEncapsulation.ShadowDom은 Shadow DOM을 기본적으로 지원하는 브라우저에서만 작동합니다. 모든 브라우저가 이를 지원하는 것은 아니므로 ViewEncapsulation.Emulated가 권장되는 기본 모드입니다.
예를 들어 다음 예에서는 ViewEncapsulation.ShadowDom 을 사용합니다.
@요소({ 선택기: '사용자-하위', templateUrl: 'UserChild.comComponent.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-팀> </hero-details>
이러한 속성은 두 가지가 있습니다.
세부정보_nghost | 속성은 | |
---|---|---|
기본 Shadow DOM 래퍼의 ShadowRoots가 되는 구성 요소 뷰를 래핑하는 요소에 추가 됩니다 | . | 이는 일반적으로 구성 요소의 호스트 요소의 경우입니다 . |
_ngcontent는 | 구성 요소 보기의 하위 요소에 추가되며 이러한 속성은 요소를 해당 시뮬레이션된 ShadowRoot(일치하는 _nghost 속성이 있는 호스트 요소)에 일치시키는 데 사용됩니다. |
이러한 속성의 정확한 값은 Angular의 비공개 구현 세부 사항입니다. 자동으로 생성되므로 애플리케이션 코드에서 참조하면 안 됩니다.
DOM의 일부에 주입되는 생성된 구성 요소 스타일을 대상으로 합니다.
[_nghost-pmm-5] { 디스플레이: 블록; 테두리: 1px 단색 검정; } h4[_ngcontent-pmm-6] { 배경색: 흰색; 테두리: 1px 실선 #777; }
이러한 스타일은 후처리되어 각 CSS 선택기가 적절한 _nghost 또는 _ngcontent 속성으로 강화됩니다. 이러한 수정된 선택기를 사용하면 스타일이 격리되고 대상화된 방식으로 구성 요소의 보기에 적용됩니다.
<p>아이들이 일해요!</p>
p{ 색상: 녹색; }
@요소({ 선택기: 'app-child', templateUrl: './child.comComponent.html', styleUrls: ['./child.comComponent.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>첫 번째: {{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>
피{ 색상: 녹색; } .red-글꼴 { 색상: 빨간색; }
@요소({ 선택기: 'app-child', templateUrl: './child.comComponent.html', styleUrls: ['./child.comComponent.scss'], 캡슐화: ViewEncapsulation.None }) 내보내기 클래스 ChildComponent가 OnInit를 구현합니다. ... }
Angular2에서 ViewEncapsulation.Native를 사용합니다.
@요소({ ..., 캡슐화: ViewEncapsulation.Native }) 내보내기 클래스 UserComponent {
ViewEncapsulation.Native 설정으로 인해 기본 Shadow DOM 기능이 사용됩니다. Angular는 브라우저에서 지원하는 Shadow DOM 형식에 따라 구성 요소를 렌더링합니다. 실제로 이는 이후의 ViewEncapsulation.ShadowDom입니다.
Angular 뷰 캡슐화의 세 가지 방법과 각각의 특성을 소개했습니다. 일상 작업에서는 특정 시나리오에 따라 어떤 캡슐화 방법을 선택해야 합니다.