Home > Article > Web Front-end > How does Angular implement view encapsulation? Let's talk about three packaging modes
AngularHow to encapsulate views? The following article will give you an in-depth understanding of the three methods of Angular Encapsulation. I hope it will be helpful to you!
In daily work, when we define a Component, we must consider its encapsulation encapsulation, that is Say whether you want the style defined in this component to apply only to this component, or whether you want it to apply globally. In Angular, a component's styles can be encapsulated within the component's host element so that they don't affect the rest of the application. The Component decorator provides encapsulation options that can be used to control how view encapsulation is applied on a per-component basis. [Related tutorial recommendations: "angular tutorial"]
There are three encapsulation modes in Angular, namely ViewEncapsulation.ShadowDom and ViewEncapsulation. Emulated,ViewEncapsulation.None.
export enum ViewEncapsulation { /** * Emulates a native Shadow DOM encapsulation behavior by adding a specific attribute to the * component's host element and applying the same attribute to all the CSS selectors provided * via {@link Component#styles styles} or {@link Component#styleUrls styleUrls}. * * This is the default option. */ Emulated = 0, /** * Doesn't provide any sort of CSS style encapsulation, meaning that all the styles provided * via {@link Component#styles styles} or {@link Component#styleUrls styleUrls} are applicable * to any HTML element of the application regardless of their host Component. */ None = 2, /** * Uses the browser's native Shadow DOM API to encapsulate CSS styles, meaning that it creates * a ShadowRoot for the component's host element which is then used to encapsulate * all the Component's styling. */ ShadowDom = 3 }
If not provided, the value will be obtained from CompilerOptions. The default compiler option is ViewEncapsulation.Emulated.
If the policy is set to ViewEncapsulation.Emulated and the component does not specify styles or styleUrls, it will automatically switch to ViewEncapsulation.None.
Have you found the enumeration type? Why is there no 1? More on this later.
Put aside the encapsulation of ShadowDom in Angular, let’s first take a look at what ShadowDOM is.
Shadow DOM allows a hidden DOM tree to be attached to the regular DOM tree - it starts with the shadow root node. In this Below the root node, it can be any element, just like ordinary DOM elements.
Here, there are some Shadow DOM-specific terms that we need to understand:
You can manipulate the Shadow DOM in the same way as a regular DOM - such as adding child nodes, setting properties, and adding your own style to the node (for example, through the element.style property ), or add styles to the entire Shadow DOM (such as adding styles within the element). The difference is that elements inside Shadow DOM will never affect elements outside it (except :focus-within), which facilitates encapsulation.
Let’s look at a simple example.
nbsp;html> <meta> <meta> <meta> <title>Shadow DOM</title> <style> span{ color: green; } </style> <span>我是Root</span> <div></div> <script> let app = document.querySelector('#app'); let shadow1 = app.attachShadow({ mode: 'open'}); let style1 = document.createElement('style'); style1.appendChild(document.createTextNode("span{color: red;}")); shadow1.appendChild(style1); let span1 = document.createElement('span'); span1.textContent = 'I am span.'; shadow1.appendChild(span1); </script>
The above example defines the global span style and also defines the span style in shadowDOM. It can be seen that they are not affected by each other.
After understanding what ShadowDOM is, let’s take a look at the encapsulation of ShadowDOM in Angular.
Angular 使用浏览器内置的 Shadow DOM API 将组件的视图包含在 ShadowRoot(用作组件的宿主元素)中,并以隔离的方式应用所提供的样式。ViewEncapsulation.ShadowDom 仅适用于内置支持 shadow DOM 的浏览器。并非所有浏览器都支持它,这就是为什么 ViewEncapsulation.Emulated 是推荐和默认模式的原因。
比如下面的这个例子,使用ViewEncapsulation.ShadowDom。
@Component({ selector: 'user-child', templateUrl: 'UserChild.component.html', styles: [` h3{ color: red; } `], encapsulation: ViewEncapsulation.ShadowDom }) export class UserChildComponent implements OnInit { ...... }
从运行的页面上看到,user-child组件内部被封装成了一个ShadowDOM,style也被封装在了里面,并不会对外部的样式造成影响。
Angular 会修改组件的 CSS 选择器,使它们只应用于组件的视图,不影响应用程序中的其他元素(模拟 Shadow DOM 行为)。
使用模拟视图封装时,Angular 会预处理所有组件的样式,以便它们仅应用于组件的视图。在正运行的 Angular 应用程序的 DOM 中,使用模拟视图封装模式的组件所在的元素附加了一些额外的属性:
<hero-details> <h3>Mister Fantastic</h3> <hero-team> <h4>Team</h4> </hero-team> </hero-details>
有两种这样的属性:
属性 | 详情 |
---|---|
_nghost | 被添加到包裹组件视图的元素中,这将是本机 Shadow DOM 封装中的 ShadowRoots。组件的宿主元素通常就是这种情况。 |
_ngcontent | 被添加到组件视图中的子元素上,这些属性用于将元素与其各自模拟的 ShadowRoots(具有匹配 _nghost 属性的宿主元素)相匹配。 |
这些属性的确切值是 Angular 的私有实现细节。它们是自动生成的,你不应在应用程序代码中引用它们。
它们以生成的组件样式为目标,这些样式会被注入到 DOM 的 部分:
[_nghost-pmm-5] { display: block; border: 1px solid black; } h4[_ngcontent-pmm-6] { background-color: white; border: 1px solid #777; }
这些样式经过后期处理,以便每个 CSS 选择器都使用适当的 _nghost 或 _ngcontent 属性进行扩充。这些修改后的选择器可以确保样式以隔离和有针对性的方式应用于组件的视图。
<p>child works!</p>
p{ color: green; }
@Component({ selector: 'app-child', templateUrl: './child.component.html', styleUrls: ['./child.component.scss'], encapsulation: ViewEncapsulation.Emulated }) export class ChildComponent implements OnInit { ...... }
ViewEncapsulation.Emulated 设置的结果是没有 Shadow DOM,但是通过 Angular 提供的样式包装机制来封装组件,使得组件的样式不受外部影响。虽然样式仍然是应用到整个 document,但 Angular 为 p创建了一个 [_ngcontent-oow-c11] 选择器。可以看出,我们为组件定义的样式,被 Angular 修改了。简单来说,尽管是也是全局样式,但是由于自动选择器的原因,并不会影响其他组件的样式。如果手动在其他元素上也添加这个属性,则样式也会应用到这元素上。
Angular 不应用任何形式的视图封装,这意味着为组件指定的任何样式实际上都是全局应用的,并且可以影响应用程序中存在的任何 HTML 元素。这种模式本质上与将样式包含在 HTML 本身中是一样的。
parent:
<p>parent works!{{count}}</p> <p>第一个:{{count}}</p> <span>parent</span> <app-child></app-child>
child:
<p>child works!</p> Child
p{ color: green; } .red-font { color: red; }
@Component({ selector: 'app-child', templateUrl: './child.component.html', styleUrls: ['./child.component.scss'], encapsulation: ViewEncapsulation.None }) export class ChildComponent implements OnInit { ...... }
在Angular2中使用ViewEncapsulation.Native。
@Component({ ..., encapsulation: ViewEncapsulation.Native }) export class UserComponent {
ViewEncapsulation.Native 设置的结果是使用原生的 Shadow DOM 特性。Angular 会把组件按照浏览器支持的 Shadow DOM 形式渲染。其实这种就是后来的ViewEncapsulation.ShadowDom。
我们介绍了Angular视图封装的三种方式,各自的特点,日常工作中要根据特定的场景去选择哪种封装方式。
更多编程相关知识,请访问:编程视频!!
The above is the detailed content of How does Angular implement view encapsulation? Let's talk about three packaging modes. For more information, please follow other related articles on the PHP Chinese website!