En el trabajo diario, cuando definimos un Componente , debemos considerar su encapsulación , es decir, ¿esperas que el estilo definido en este componente actúe solo sobre este componente, o quieres que actúe globalmente? En Angular, los estilos de un componente se pueden encapsular dentro del elemento host del componente para que no afecten al resto de la aplicación. El decorador de componentes proporciona opciones de encapsulación que se pueden utilizar para controlar cómo se aplica la encapsulación de vistas por componente. [Recomendaciones de tutoriales relacionados: "tutorial angular"]
Hay tres modos de encapsulación en Angular, a saber, ViewEncapsulation.ShadowDom, ViewEncapsulation.Emulated y ViewEncapsulation.None.
exportar enumeración ViewEncapsulation { /** * Emula un comportamiento de encapsulación nativo de Shadow DOM agregando un atributo específico al * elemento host del componente y aplicando el mismo atributo a todos los selectores CSS proporcionados * a través de {@link Component#styles estilos} o {@link Component#styleUrls styleUrls}. * *Esta es la opción predeterminada. */ Emulado = 0, /** * No proporciona ningún tipo de encapsulación de estilos CSS, lo que significa que todos los estilos proporcionados * a través de {@link Component#styles estilos} o {@link Component#styleUrls styleUrls} son aplicables * a cualquier elemento HTML de la aplicación independientemente de su componente anfitrión. */ Ninguno = 2, /** * Utiliza la API Shadow DOM nativa del navegador para encapsular estilos CSS, lo que significa que crea * un ShadowRoot para el elemento anfitrión del componente que luego se usa para encapsular * todo el estilo del componente. */ Dominio de las Sombras=3 }
Si no se proporciona, el valor se obtiene de CompilerOptions. La opción predeterminada del compilador es ViewEncapsulation.Emulated.
Si la política está configurada en ViewEncapsulation.Emulated y el componente no especifica estilos o styleUrls, cambiará automáticamente a ViewEncapsulation.None.
¿Descubrió por qué no hay 1 en el tipo de enumeración ? Más sobre esto más adelante.
Dejemos de lado la encapsulación de ShadowDom en Angular, primero echemos un vistazo a qué es ShadowDOM.
Shadow DOM permite adjuntar un árbol DOM oculto al árbol DOM normal; comienza con el nodo raíz de la sombra Debajo de este nodo raíz, puede ser cualquier elemento, como un elemento DOM normal.
Aquí hay algunos términos específicos de Shadow DOM que debemos comprender:
Puede manipular Shadow DOM de la misma manera que un DOM normal, como agregar nodos secundarios, configurar propiedades y agregar su propio estilo al nodo (por ejemplo, a través de la propiedad element.style) o agregar estilos a todo el nodo. Shadow DOM (por ejemplo, agregar estilos dentro de elementos). La diferencia es que los elementos dentro de Shadow DOM nunca afectarán a los elementos fuera de él (excepto: focus-within), lo que facilita la encapsulación.
Veamos un ejemplo sencillo.
<!DOCTYPE html> <html> <cabeza> <meta juego de caracteres="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta nombre="viewport" content="ancho=ancho-dispositivo, escala-inicial=1.0"> <título>DOM en la sombra</título> <estilo> durar{ color: verde; } </estilo> </cabeza> <cuerpo> <span>Soy root</span> <div id="aplicación"></div> <guión> let aplicación = document.querySelector('#app'); let shadow1 = app.attachShadow({ modo: 'abrir'}); let style1 = document.createElement('estilo'); style1.appendChild(document.createTextNode("span{color: rojo;}")); sombra1.appendChild(estilo1); let span1 = document.createElement('span'); span1.textContent = 'Soy span.'; sombra1.appendChild(span1); </script> </cuerpo> </html>
El ejemplo anterior define el estilo de extensión global y el estilo de extensión en ShadowDOM. Se puede ver que no se afectan entre sí.
Después de comprender qué es ShadowDOM, echemos un vistazo a la encapsulación de ShadowDOM en Angular.
Angular utiliza la API Shadow DOM integrada del navegador para envolver la vista de un componente en un ShadowRoot (que sirve como elemento anfitrión del componente) y aplicar los estilos proporcionados de forma aislada. ViewEncapsulation.ShadowDom solo funciona en navegadores con soporte integrado para Shadow DOM. No todos los navegadores lo admiten, por lo que ViewEncapsulation.Emulated es el modo recomendado y predeterminado.
Por ejemplo, en el siguiente ejemplo, utilice ViewEncapsulation.ShadowDom .
@Componente({ selector: 'usuario-niño', URL de plantilla: 'UserChild.component.html', estilos: [` h3{ color: rojo; } `], encapsulación: ViewEncapsulation.ShadowDom }) clase de exportación UserChildComponent implementa OnInit { ... }
Desde la página en ejecución, podemos ver que el componente usuario-hijo está encapsulado internamente en un ShadowDOM, y el estilo también está encapsulado internamente, lo que no afectará el estilo externo.
Angular modifica los selectores CSS de un componente para que solo se apliquen a la vista del componente y no afecten a otros elementos de la aplicación (emulando el comportamiento de Shadow DOM).
Cuando se utiliza la encapsulación de vista simulada, Angular preprocesa todos los estilos de componentes para que solo se apliquen a la vista del componente. En el DOM de la aplicación Angular en ejecución, el elemento que contiene el componente que utiliza el patrón de encapsulación de vista simulada tiene algunos atributos adicionales adjuntos:
<hero-details _nghost-pmm-5> <h3 _ngcontent-pmm-5>Señor Fantástico</h3> <equipo-héroe _ngcontent-pmm-5 _nghost-pmm-6> <h4 _ngcontent-pmm-6>Equipo</h4> </equipo-hero> </hero-details>
Hay dos atributos de este tipo:
El atributo | detalles_nghost |
---|---|
se | agrega al elemento que envuelve la vista del componente , que será ShadowRoots en el contenedor nativo Shadow DOM. Este suele ser el caso del elemento anfitrión del componente . |
_ngcontent | se agrega a los elementos secundarios en las vistas de componentes , y estos atributos se usan para hacer coincidir los elementos con sus respectivos ShadowRoots simulados (elementos anfitriones con atributos _nghost coincidentes). |
Los valores exactos de estas propiedades son un detalle de implementación privado de Angular. Se generan automáticamente y no debes hacer referencia a ellos en el código de tu aplicación.
Se dirigen a estilos de componentes generados, que se inyectan en partes del DOM:
[_nghost-pmm-5] { mostrar: bloquear; borde: 1px negro sólido; } h4[_ngcontent-pmm-6] { color de fondo: blanco; borde: 1px sólido #777; }
Estos estilos se procesan posteriormente para que cada selector CSS se aumente con el atributo _nghost o _ngcontent apropiado. Estos selectores modificados garantizan que los estilos se apliquen a las vistas de un componente de forma aislada y específica.
<p>¡niño trabaja!</p>
p{ color: verde; }
@Componente({ selector: 'aplicación-niño', URL de plantilla: './child.component.html', URL de estilo: ['./child.component.scss'], encapsulación: ViewEncapsulation.Emulated }) clase de exportación ChildComponent implementa OnInit { ... }
El resultado de la configuración ViewEncapsulation.Emulated es que no hay Shadow DOM, pero el componente se encapsula a través del mecanismo de empaquetado de estilos proporcionado por Angular, de modo que el estilo del componente no se ve afectado por influencias externas. Aunque el estilo todavía se aplica a todo el documento, Angular crea un selector [_ngcontent-oow-c11] para p. Se puede ver que Angular ha modificado el estilo que definimos para el componente. En pocas palabras, aunque es un estilo global, no afectará los estilos de otros componentes debido al selector automático. Si agrega manualmente este atributo a otros elementos, el estilo también se aplicará a este elemento.
Angular no aplica ninguna forma de encapsulación de vista, lo que significa que cualquier estilo especificado para el componente en realidad se aplica globalmente y puede afectar cualquier elemento HTML presente en la aplicación. Este patrón es esencialmente el mismo que incluir estilos en el propio HTML.
padre:
<p #caption>¡el padre trabaja!{{count}}</p> <p #caption>Primero: {{count}}</p> <span class="red-font">padre</span> <app-child></app-child>
niño:
<div style="border: 1px verde sólido;"> <p>¡niño trabaja!</p> <span class="red-font">Niño</span> </div>
p{ color: verde; } .fuente roja { color: rojo; }
@Componente({ selector: 'aplicación-niño', URL de plantilla: './child.component.html', URL de estilo: ['./child.component.scss'], encapsulación: ViewEncapsulation.Ninguno }) clase de exportación ChildComponent implementa OnInit { ... }Uso
ViewEncapsulation.Native en Angular2.
@Componente({ ..., encapsulación: ViewEncapsulation.Native }) exportar clase UserComponent {
La configuración ViewEncapsulation.Native da como resultado el uso de la función nativa Shadow DOM. Angular representará el componente de acuerdo con el formato Shadow DOM admitido por el navegador. De hecho, este es el ViewEncapsulation.ShadowDom posterior.
hemos introducido tres métodos de encapsulación de vista angular y sus respectivas características. En el trabajo diario, debe elegir qué método de encapsulación según escenarios específicos.