Angular - 视图封装



视图封装是一种将给定视图的样式与应用程序的其他部分封装的技术。一般来说,应用于 HTML 文档的 CSS 样式会影响整个文档。Angular 框架也同样适用。这种默认行为在某些情况下(例如全局样式)是有利的,但同时它也可能无意中影响应用程序的特定部分(例如具有特定样式的特殊按钮/链接)。为了确保应用程序特定部分的样式不会受到影响,可以使用 Angular 提供的视图封装概念。

选项

Angular 在组件装饰器中提供了一个属性 `encapsulation` 来指导如何保护组件样式。`encapsulation` 的选项如下:

  • None (ViewEncapsulation.None)

  • Emulated (ViewEncapsulation.Emulated)

  • ShadowDom (ViewEncapsulation.ShadowDom)

None

None 选项不会对保护组件内元素的样式做任何事情。组件视图将暴露于所有全局样式并受其影响。

让我们创建一个简单的组件,并检查组件视图是如何生成和渲染的。

步骤1:创建一个新组件,`view-encapsulation-sample`

$ ng generate component view-encapsulation-sample
CREATE src/app/view-encapsulation-sample/view-encapsulation-sample.component.css (0 bytes)
CREATE src/app/view-encapsulation-sample/view-encapsulation-sample.component.html (40 bytes)
CREATE src/app/view-encapsulation-sample/view-encapsulation-sample.component.spec.ts (680 bytes)
CREATE src/app/view-encapsulation-sample/view-encapsulation-sample.component.ts (276 bytes)
UPDATE src/app/app.module.ts (547 bytes)

步骤2:在组件中添加 None 视图封装,如下所示:

import { Component, ViewEncapsulation } from '@angular/core';

@Component({
   selector: 'app-view-encapsulation-sample',
   templateUrl: './view-encapsulation-sample.component.html',
   styleUrls: ['./view-encapsulation-sample.component.css'],
   encapsulation: ViewEncapsulation.None
})
export class ViewEncapsulationSampleComponent {

}

步骤3:更改模板 `view-encapsulation-sample.component.html` 并添加两个容器,如下所示:

<div>I am inside the none container</div>
<div class="mystyle">I am inside the none container and has my own style</div>

这里,第一个容器没有任何样式或类,更容易受到全局样式的影响。第二个容器具有类属性,但仍然有可能受到全局样式的影响。

步骤4:在组件 CSS 文件 `view-encapsulation-sample.component.css` 中应用样式,如下所示:

div.mystyle { color: brown }

步骤5:将组件添加到应用程序组件 `app.component.html` 中,如下所示:

<app-view-encapsulation-sample />

<router-outlet></router-outlet>

步骤6:运行应用程序并检查生成的 HTML 和 CSS

<app-view-encapsulation-sample _ngcontent-ng-c750168442="">
   <div>I am inside the none container</div>
   <div class="mystyle">I am inside the none container and has my own style</div>
</app-view-encapsulation-sample>
div.mystyle {
   color: brown;
}

在这里,您可以清楚地看到生成的样式和元素是普通的,没有应用任何保护措施,应用程序的外观如下所示:

步骤7:在我们的全局 CSS 资产 `styles.css` 中添加一个针对 div 标签的样式,然后重新运行应用程序

div { color: blue }

现在,第一个容器的颜色变为蓝色,如下所示:

Emulated

Emulated 选项将更改样式,使其仅应用于组件内的元素。组件的元素在任何情况下都不会受到全局样式的影响。

让我们更改我们的应用程序并应用 Emulated 选项,如下所示:

import { Component, ViewEncapsulation } from '@angular/core';

@Component({
   selector: 'app-view-encapsulation-sample',
   templateUrl: './view-encapsulation-sample.component.html',
   styleUrls: ['./view-encapsulation-sample.component.css'],
   encapsulation: ViewEncapsulation.Emulated
})
export class ViewEncapsulationSampleComponent {
}

现在,重新运行应用程序并检查输出。

<app-view-encapsulation-sample _ngcontent-ng-c750168442="" _nghost-ng-c2076704321="">
   <div _ngcontent-ng-c2076704321="">I am inside the none container</div>
   <div _ngcontent-ng-c2076704321="" class="mystyle">I am inside the none container and has my own style</div>
</app-view-encapsulation-sample>
div.mystyle[_ngcontent-ng-c2076704321] {
   color: brown;
}

现在,容器通过使用 Angular 生成的特殊属性(_ngcontent-ng-c2076704321)应用样式来保护,并且 CSS 不受全局样式的影响。

ShadowDom

ShadowDom 选项将应用 HTML 原生的 shadow dom 概念来保护组件的样式。组件的元素在任何情况下都不会受到全局样式的影响,因为它完全隐藏了 shadowDOM 概念。

更改我们的应用程序并应用 ShadowDOM 选项,如下所示:

import { Component, ViewEncapsulation } from '@angular/core';

@Component({
   selector: 'app-view-encapsulation-sample',
   templateUrl: './view-encapsulation-sample.component.html',
   styleUrls: ['./view-encapsulation-sample.component.css'],
   encapsulation: ViewEncapsulation.ShadowDom
})
export class ViewEncapsulationSampleComponent {

}

现在,重新运行应用程序并检查输出。

shadowdom

现在,两个容器都受到原生 shadowDOM 概念的保护,并且不受全局样式的影响。

在应用程序中应用不同的封装

组件的视图封装可以与应用程序中使用的其他组件不同,因为视图封装是基于每个组件应用的。即使是嵌套组件也可以根据组件需求具有不同的视图封装选项。Angular 甚至在非常复杂的嵌套组件树中也会根据指示应用封装。

广告