No trabalho diário, quando definimos um Componente , devemos considerar o seu encapsulamento , ou seja, você espera que o estilo definido neste componente atue apenas sobre este componente, ou deseja que ele atue globalmente. No Angular, os estilos de um componente podem ser encapsulados no elemento host do componente para que não afetem o restante do aplicativo. O decorador Component fornece opções de encapsulamento que podem ser usadas para controlar como o encapsulamento de visualização é aplicado por componente. [Recomendações do tutorial relacionado: "tutorial angular"]
Existem três modos de encapsulamento no Angular, a saber, ViewEncapsulation.ShadowDom, ViewEncapsulation.Emulated e ViewEncapsulation.None.
exportar enum ViewEncapsulation { /** * Emula um comportamento de encapsulamento nativo do Shadow DOM adicionando um atributo específico ao * elemento host do componente e aplicação do mesmo atributo a todos os seletores CSS fornecidos * via {@link Component#styles estilos} ou {@link Component#styleUrls styleUrls}. * * Esta é a opção padrão. */ Emulado = 0, /** * Não fornece nenhum tipo de encapsulamento de estilo CSS, o que significa que todos os estilos fornecidos * via {@link Component#styles styles} ou {@link Component#styleUrls styleUrls} são aplicáveis * para qualquer elemento HTML do aplicativo, independentemente do componente host. */ Nenhum = 2, /** * Usa a API Shadow DOM nativa do navegador para encapsular estilos CSS, o que significa que ele cria * um ShadowRoot para o elemento host do componente que é então usado para encapsular * todo o estilo do componente. */ ShadowDom=3 }
Se não for fornecido, o valor será obtido de CompilerOptions. A opção padrão do compilador é ViewEncapsulation.Emulated.
Se a política estiver definida como ViewEncapsulation.Emulated e o componente não especificar estilos ou styleUrls, ele mudará automaticamente para ViewEncapsulation.None.
Você descobriu por que não existe 1 no tipo de enumeração ? Mais sobre isso mais tarde.
Deixando de lado o encapsulamento do ShadowDom no Angular, vamos primeiro dar uma olhada no que é ShadowDOM.
Shadow DOM permite que uma árvore DOM oculta seja anexada à árvore DOM normal - ela começa com o nó raiz sombra Abaixo deste nó raiz, pode ser qualquer elemento, assim como um elemento DOM comum.
Aqui, existem alguns termos específicos do Shadow DOM que precisamos entender:
Você pode manipular o Shadow DOM da mesma maneira que um DOM normal - como adicionar nós filhos, definir propriedades e adicionar seu próprio estilo ao nó (por exemplo, por meio da propriedade element.style) ou adicionar estilos ao todo Shadow DOM (por exemplo, adicionar estilos dentro de elementos). A diferença é que os elementos dentro do Shadow DOM nunca afetarão os elementos fora dele (exceto :focus-within), o que facilita o encapsulamento.
Vejamos um exemplo simples.
<!DOCTYPEhtml> <html> <cabeça> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="largura=largura do dispositivo, escala inicial=1,0"> <title>Shadow DOM</title> <estilo> intervalo{ cor: verde; } </estilo> </head> <corpo> <span>Eu sou Root</span> <div id="app"></div> <roteiro> deixe app = document.querySelector('#app'); deixe shadow1 = app.attachShadow({modo: 'abrir'}); deixe estilo1 = document.createElement('estilo'); style1.appendChild(document.createTextNode("span{cor: vermelho;}")); shadow1.appendChild(estilo1); deixe span1 = document.createElement('span'); span1.textContent = 'Eu sou span.'; shadow1.appendChild(span1); </script> </body> </html>
O exemplo acima define o estilo span global e o estilo span no shadowDOM. Pode-se ver que eles não são afetados um pelo outro.
Depois de entender o que é ShadowDOM, vamos dar uma olhada no encapsulamento de ShadowDOM em Angular.
Angular usa a API Shadow DOM integrada do navegador para agrupar a visualização de um componente em um ShadowRoot (que serve como elemento host do componente) e aplicar os estilos fornecidos de maneira isolada. ViewEncapsulation.ShadowDom funciona apenas em navegadores com suporte integrado para shadow DOM. Nem todos os navegadores oferecem suporte, e é por isso que ViewEncapsulation.Emulated é o modo recomendado e padrão.
Por exemplo, no exemplo a seguir, use ViewEncapsulation.ShadowDom .
@Componente({ seletor: 'usuário-filho', templateUrl: 'UserChild.component.html', estilos: [` h3{ cor: vermelho; } `], encapsulamento: ViewEncapsulation.ShadowDom }) classe de exportação UserChildComponent implementa OnInit { ... }
Na página em execução, podemos ver que o componente usuário-filho está encapsulado internamente em um ShadowDOM, e o estilo também está encapsulado internamente, o que não afetará o estilo externo.
Angular modifica os seletores CSS de um componente para que eles se apliquem apenas à visualização do componente e não afetem outros elementos no aplicativo (emulando o comportamento do Shadow DOM).
Ao usar o encapsulamento de visualização simulada, o Angular pré-processa todos os estilos de componente para que eles se apliquem apenas à visualização do componente. No DOM do aplicativo Angular em execução, o elemento que contém o componente que usa o padrão de encapsulamento de visualização simulada possui alguns atributos adicionais anexados:
<hero-details _nghost-pmm-5> <h3 _ngcontent-pmm-5>Senhor Fantástico</h3> <equipe herói _ngcontent-pmm-5 _nghost-pmm-6> <h4 _ngcontent-pmm-6>Equipe</h4> </hero-team> </hero-details>
Existem dois desses atributos:
O | atributodetails_nghost |
---|---|
é | adicionado ao elemento que envolve o componente view , que será o ShadowRoots no wrapper nativo do Shadow DOM. Geralmente esse é o caso do elemento host do componente . |
_ngcontent | é adicionado a elementos filhos em visualizações de componentes e esses atributos são usados para combinar elementos com seus respectivos ShadowRoots simulados (elementos host com atributos _nghost correspondentes). |
Os valores exatos dessas propriedades são um detalhe privado da implementação do Angular. Eles são gerados automaticamente e você não deve referenciá-los no código do seu aplicativo.
Eles têm como alvo estilos de componentes gerados, que são injetados em partes do DOM:
[_nghost-pmm-5] { exibição: bloco; borda: 1px preto sólido; } h4[_ngcontent-pmm-6] { cor de fundo: branco; borda: 1px sólido #777; }
Esses estilos são pós-processados para que cada seletor CSS seja aumentado com o atributo _nghost ou _ngcontent apropriado. Esses seletores modificados garantem que os estilos sejam aplicados às visualizações de um componente de maneira isolada e direcionada.
<p>criança trabalha!</p>
p{ cor: verde; }
@Component({ seletor: 'app-child', templateUrl: './child.component.html', styleUrls: ['./child.component.scss'], encapsulamento: ViewEncapsulation.Emulated }) classe de exportação ChildComponent implementa OnInit { ... }
O resultado da configuração ViewEncapsulation.Emulated é que não há Shadow DOM, mas o componente é encapsulado por meio do mecanismo de empacotamento de estilo fornecido pelo Angular, para que o estilo do componente não seja afetado por influências externas. Embora o estilo ainda seja aplicado a todo o documento, Angular cria um seletor [_ngcontent-oow-c11] para p. Pode-se observar que o estilo que definimos para o componente foi modificado pelo Angular. Simplificando, embora seja um estilo global, não afetará os estilos de outros componentes devido ao seletor automático. Se você adicionar manualmente este atributo a outros elementos, o estilo também será aplicado a este elemento.
Angular não aplica nenhuma forma de encapsulamento de visualização, o que significa que quaisquer estilos especificados para o componente são realmente aplicados globalmente e podem afetar qualquer elemento HTML presente no aplicativo. Esse padrão é essencialmente o mesmo que incluir estilos no próprio HTML.
pai:
<p #caption>pai funciona!{{count}}</p> <p #caption>Primeiro: {{count}}</p> <span class="red-font">pai</span> <app-child></app-child>
filho:
<div style="border: 1px solid green;"> <p>criança trabalha!</p> <span class="red-font">Criança</span> </div>
p{ cor: verde; } .red-font { cor: vermelho; }
@Component({ seletor: 'app-child', templateUrl: './child.component.html', styleUrls: ['./child.component.scss'], encapsulamento: ViewEncapsulation.None }) classe de exportação ChildComponent implementa OnInit { ... }
Use ViewEncapsulation.Native em Angular2.
@Componente({ ..., encapsulamento: ViewEncapsulation.Native }) classe de exportação UserComponent {
A configuração ViewEncapsulation.Native resulta no uso do recurso Shadow DOM nativo. Angular renderizará o componente de acordo com o formato Shadow DOM suportado pelo navegador. Na verdade, este é o ViewEncapsulation.ShadowDom posterior.
apresentamos três métodos de encapsulamento de visão Angular e suas respectivas características. No trabalho diário, você deve escolher qual método de encapsulamento de acordo com cenários específicos.