这篇探讨一下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
的场景有:
- 第三方库的样式覆盖,因为第三方库的样式有时候是无法直接通过选择器来修改的,这时候就需要使用
::ng-deep
。
为什么要配合:host
一起使用?
在我们日常的项目中,::ng-deep
很少单独使用,由上面对ng::deep
的描述可知,它相当于将样式变成了全局样式,如果不加:host
,那么这个样式会影响到所有的组件,加了:host
,则只会影响到当前组件及其后代组件。
注意:
- 使用了
::ng-deep
的组件,只有显示在页面上时(该组建对应的前端路由生效时),才会影响其他组件的样式。如果该组件没有显示在页面上,那么它的样式是不会影响其他组件的。 - 如果当前页面只显示了使用了
::ng-deep
的组件,而没有显示其他组件,那么ng::deep
的样式也不会影响到其他组件。
也就是说使用了::ng-deep
的组件,只有和其他组件一起显示在页面上,才会影响其他组件的样式。
实际的例子,假设有组件A在其样式文件中使用了ng::deep
,对于三级标题,将其文本设置为红色。
1 | /* style for Component A */ |
组件B也有一个三级标题,但是没有设置样式。
如果组件A和组件B同时显示在页面上,那么组件A的样式会覆盖组件B的样式,此时页面上的所有h3标题都会显示为红色。
1 | <app-component-a></app-component-a> |
我们在浏览器中inspect,可以看到组件A设置的三级标题样式放到了整个html的head部分。
如果组件A中在::ng-deep
前加上:host
,则只有组件A中的h3标题显示为红色,组件B中的h3标题不会受到影响。
1 | /* style for Component A */ |
为啥加上:host
后,就不影响别的组件了呢,因为:host表示这个样式只针对当前组件和其子组件生效,由生成后的css文件也可看出这点,请看下图。
在h3
之前多了一个限定字符串_nghost-ng-c2124967347
,这个字符串正好是组件A的选择器,这样就保证了这个样式只会影响到组件A。而组件B有一个不同的选择器_nghost-ng-c2124967348
,所以组件B的h3标题不会受到影响。
如果我们不加:host
,那么生成的css文件中就没有这个限定字符串,这样就会影响到所有的组件。
::ng-deep
只对ViewEncapsulation.Emulated
有效
::ng-deep
只对encapsulation: ViewEncapsulation.Emulated
有效,对于encapsulation: ViewEncapsulation.ShadowDom
和encapsulation: ViewEncapsulation.None
无效。