0%

angular-ngdeep

这篇探讨一下Angular中::ng-deep伪类的用法。

::ng-deep是什么?

以下是::ng-deep的官方描述:

(deprecated) /deep/, >>>, and ::ng-deep
Component styles normally apply only to the HTML in the component’s own template.

Applying the ::ng-deep pseudo-class to any CSS rule completely disables view-encapsulation for that rule. Any style with ::ng-deep applied becomes a global style. In order to scope the specified style to the current component and all its descendants, be sure to include the :host selector before ::ng-deep. If the ::ng-deep combinator is used without the :host pseudo-class selector, the style can bleed into other components.

为什么需要::ng-deep?

根据我的经验,使用::ng-deep的场景有:

  1. 第三方库的样式覆盖,因为第三方库的样式有时候是无法直接通过选择器来修改的,这时候就需要使用::ng-deep

为什么要配合:host一起使用?

在我们日常的项目中,::ng-deep很少单独使用,由上面对ng::deep的描述可知,它相当于将样式变成了全局样式,如果不加:host,那么这个样式会影响到所有的组件,加了:host,则只会影响到当前组件及其后代组件。

注意:

  1. 使用了::ng-deep的组件,只有显示在页面上时(该组建对应的前端路由生效时),才会影响其他组件的样式。如果该组件没有显示在页面上,那么它的样式是不会影响其他组件的。
  2. 如果当前页面只显示了使用了::ng-deep的组件,而没有显示其他组件,那么ng::deep的样式也不会影响到其他组件。

也就是说使用了::ng-deep的组件,只有和其他组件一起显示在页面上,才会影响其他组件的样式。

实际的例子,假设有组件A在其样式文件中使用了ng::deep,对于三级标题,将其文本设置为红色。

1
2
3
4
/* style for Component A */
::ng-deep h3 {
color: red;
}

组件B也有一个三级标题,但是没有设置样式。

如果组件A和组件B同时显示在页面上,那么组件A的样式会覆盖组件B的样式,此时页面上的所有h3标题都会显示为红色。

1
2
<app-component-a></app-component-a>
<app-component-b></app-component-b>

我们在浏览器中inspect,可以看到组件A设置的三级标题样式放到了整个html的head部分。

如果组件A中在::ng-deep前加上:host,则只有组件A中的h3标题显示为红色,组件B中的h3标题不会受到影响。

1
2
3
4
/* style for Component A */
:host ::ng-deep h3 {
color: red;
}

为啥加上:host后,就不影响别的组件了呢,因为:host表示这个样式只针对当前组件和其子组件生效,由生成后的css文件也可看出这点,请看下图。

h3之前多了一个限定字符串_nghost-ng-c2124967347,这个字符串正好是组件A的选择器,这样就保证了这个样式只会影响到组件A。而组件B有一个不同的选择器_nghost-ng-c2124967348,所以组件B的h3标题不会受到影响。

如果我们不加:host,那么生成的css文件中就没有这个限定字符串,这样就会影响到所有的组件。

angular-style-ngdeep

::ng-deep只对ViewEncapsulation.Emulated有效

::ng-deep只对encapsulation: ViewEncapsulation.Emulated有效,对于encapsulation: ViewEncapsulation.ShadowDomencapsulation: ViewEncapsulation.None无效。