如何以及在哪里使用:: ng-deep?


90

我是Angular 4的新手,所以谁能解释::ng-deep在Angular 4中的使用方式和位置?

实际上,我想从父组件覆盖子组件的某些CSS属性。此外,它在IE11上受支持吗?


由于/deep/::ng-deep均已弃用,建议您查看此答案stackoverflow.com/a/49308475/2275011以及有关更多详细信息和解决方案的评论。
Ferie的Ferie

Answers:


92

通常, /deep/ “shadow-piercing”可以使用组合器将样式强制降低到child components。这个选择器有一个别名>>>,现在还有另一个叫做:: ng-deep的别名。

由于/deep/ combinator已被弃用,建议使用::ng-deep

例如:

<div class="overview tab-pane" id="overview" role="tabpanel" [innerHTML]="project?.getContent( 'DETAILS')"></div>

css

.overview {
    ::ng-deep {
        p {
            &:last-child {
                margin-bottom: 0;
            }
        }
    }
}

它将应用于子组件


是否支持IE11?
Jeyabalan Thavamani

2
Angular会对其进行解析-因此您无需担心兼容性。
Simon_Weaver

仅用于子组件吗?我记得并在另一条评论中看到,它也适用于组件外部的dom元素。
yaya

我可以确认它也可以做父组件...刚刚遇到这种情况,并为此感到恼火。
Shadoweb

1
太棒了,效果很好。
阿尔弗雷多·扎穆迪奥

70

用法

::ng-deep>>>/deep/禁用特定CSS规则的视图封装,换句话说,它使您可以访问组件HTML中不包含的DOM元素。例如,如果您使用的是Angular Material(或其他类似的第三方库),则某些生成的元素在组件区域之外(例如dialog),并且您不能直接访问这些元素或使用常规CSS方式。如果要更改这些元素的样式,则可以使用以下三种方法之一,例如:

::ng-deep .mat-dialog {
  /* styles here */
}

目前,Angular团队建议仅使用EMULATED视图封装进行“深度”操作。

弃用

实际上,“深层”操作也弃用它仍然可以正常工作,因为Angular提供了预处理支持(::ng-deep今天不要急于拒绝,请先了解一下弃用实践)。

无论如何,在采用这种方法之前,我建议您先看看禁用视图封装方法(这也不是很理想,它会使您的样式泄漏到其他组件中),但是在某些情况下,这是一种更好的方法。如果决定禁用视图封装,则强烈建议使用特定的类,以避免CSS规则交叉,最后,避免样式表混乱。禁用组件.ts文件中的权限确实很容易:

@Component({
  selector: '',
  template: '',
  styles: [''],
  encapsulation: ViewEncapsulation.None  // Use to disable CSS Encapsulation for this component
})

您可以找到有关在视图中封装更多信息文章。


3
禁用视图封装将全局应用组件中的所有CSS。
Vedran

16
不要使用ViewEncapsulation.None!通过使这些样式可能泄漏到其他组件中,将会造成很多损害。
亚历克斯·克劳斯

1
@AlexKlaus,同意,这就是我在答案中提到的原因,这并不理想。实际上,我只用了一次将共享的可重复样式应用于Angular Material组件。如果尝试禁用封装,则可能会在某个时候陷入混乱。知道此选项很高兴,但是在您不确定自己是否需要此选项时,请不要使用它。
商业自杀

29

我会强调::ng-deep通过要求父级是封装的CSS类来将组件的子级限制为仅子级的重要性。

为此,重要的是::ng-deep在父类之后使用,而不是在父类之前使用,否则它将在加载组件时应用于具有相同名称的所有类。

组件CSS:

.my-component ::ng-deep .mat-checkbox-layout {
    background-color: aqua;
}

组件模板:

<h1 class="my-component">
    <mat-checkbox ....></mat-checkbox>
</h1>

结果(生成角度)css:

.my-component[_ngcontent-c1] .mat-checkbox-layout {
    background-color: aqua;
}

编辑:

您可以通过使用:host关键字而不是创建新的CSS类来实现相同的行为。

:host ::ng-deep .mat-checkbox-layout

5
男人,你的回答my-component ::ng-deep...挽救了我的一天。我花了一整天的时间尝试使用ng-deep为我的组件应用样式,并且从整个应用程序覆盖了我所有的组件。
克里斯蒂亚诺·邦巴扎

2
值得注意的是:“为了将指定的样式作用于当前组件及其所有后代(但不是全局),请确保在:: ng-deep之前包括:host选择器。” 来自:angular.io/guide/component-styles
StvnBrkdll

1
@CristianoBombazar-您将获得与:host关键字相同的行为-为清楚起见在答案中添加了注释。
Vedran

23

确保不要错过角度指南中:host-context上面的解释::ng-deephttps : //angular.io/guide/component-styles。免责声明:直到现在我都错过了它,希望早日看到它。

::ng-deep当您没有编写组件并且无权访问其源代码时,:host-context通常是很有必要的,但是当您这样做时,这可能是一个非常有用的选择。

例如,我<h1>在设计的组件内部有一个黑色标题,并且我希望能够在深色主题背景上将其更改为白色。

如果我没有访问源的权限,则可能必须在CSS中为父级执行此操作:

.theme-dark widget-box ::ng-deep h1 { color: white; }

但是,:host-context您可以在组件内部执行此操作。

 h1 
 {
     color: black;       // default color

     :host-context(.theme-dark) &
     {
         color: white;   // color for dark-theme
     }

     // OR set an attribute 'outside' with [attr.theme]="'dark'"

     :host-context([theme='dark']) &
     {
         color: white;   // color for dark-theme
     }
 }

这将在组件链中的任何位置查找,.theme-dark并将css应用于h1(如果找到)。这是一个很好的选择,可以避免过度依赖(::ng-deep虽然经常需要某种程度的反模式)。

在这种情况下,&替换为h1(这是sass / scss的工作方式),因此您可以彼此相邻地定义“普通”和主题/替代CSS,这非常方便。

请注意获取正确的数量:。因为::ng-deep有两个,:host-context只有一个。


:host(.theme-dark)如果您不想theme-dark从任何父组件继承,也可以使用。这将完全取决于您网站的CSS设计。属性也可能非常有用,并且可以单独在CSS中以复杂的方式进行组合:host([theme='dark']:not([dayofweek='tuesday'))
Simon_Weaver

还要注意,这遵循正常的CSS规则,因此,如果您在具有.theme-light类的容器中包含上述组件(带有主机上下文CSS),则该类又嵌套在容器中,.theme-dark它将仍然拾取theme-dark并应用css。但这对于'modernizr'类型类是一个很好的解决方案,或者如果您在全局范围内仅设置了一次主题,那么这是一个很好的解决方案。
Simon_Weaver

我可以使用:host-context代替:: ng-deep吗?

@eddy我现在很困,无法完全考虑到这一点,但是主机上下文几乎就像ng-deep一样,但是将DOM树向上而不是向下。因此,这绝对不等效,但您可以
Simon_Weaver

2

只是更新:

您应该使用似乎已弃用的::ng-deep而不是/deep/

每个文档:

不推荐使用穿刺阴影的后代组合器,并且从主要的浏览器和工具中删除了对它的支持。因此,我们计划放弃对Angular的支持(针对/ deep /,>>>和:: ng-deep的全部3个)。在此之前,应首选:: ng-deep以获得与工具的广泛兼容性。

你可以在这里找到


5
在本文中,它清楚地表明:: ng-deep也已被弃用:“我们计划放弃对Angular的支持(针对/ deep /,>>>和:: ng-deep的所有3种)”。
adripanico

-2

请谨慎使用:: ng-deep。我在整个应用程序中都使用它,将材质设计工具栏颜色设置为整个应用程序中的不同颜色,只是发现当应用程序正在测试工具栏颜色时,它们会相互叠加。找出原因是这些样式已成为全局样式,请参见本文。 这是一个有效的代码解决方案,不会渗入其他组件。

<mat-toolbar #subbar>
...
</mat-toolbar>

export class BypartSubBarComponent implements AfterViewInit {
  @ViewChild('subbar', { static: false }) subbar: MatToolbar;
  constructor(
    private renderer: Renderer2) { }
  ngAfterViewInit() {
    this.renderer.setStyle(
      this.subbar._elementRef.nativeElement, 'backgroundColor', 'red');
  }

}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.