【问题标题】:How and where to use ::ng-deep?如何以及在何处使用 ::ng-deep?
【发布时间】:2018-03-28 23:00:36
【问题描述】:

我是 Angular 4 的新手,谁能解释一下在 Angular 4 中如何以及在何处使用 ::ng-deep

其实我是想从父组件中覆盖一些子组件的CSS属性。另外IE11是否支持?

感谢您的帮助。

【问题讨论】:

标签: css angular angular-template


【解决方案1】:

通常 /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?
  • Angular 会对其进行解析——因此您无需担心兼容性问题。
  • 是否仅适用于子组件?我记得,正如我在另一条评论中看到的那样,它也适用于组件之外的 dom 元素。
  • 我可以确认它也有父组件...刚遇到这个案例并为此感到恼火。
【解决方案2】:

用法

::ng-deep&gt;&gt;&gt;/deep/ 禁用特定 CSS 规则的视图封装,换句话说,它允许您访问不在组件 HTML 中的 DOM 元素。例如,如果您使用 Angular Material(或任何其他类似的第三方库),则某些生成的元素位于组件区域之外(例如 dialog),您无法直接访问这些元素或使用常规的 CSS 方式。如果你想改变这些元素的样式,你可以使用这三个东西之一,例如:

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

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

弃用

“深度” 操作实际上也是 deprecated它现在仍然有效,因为 Angular 提供预处理支持(不要急于拒绝 @今天987654329@,先看看deprecation practices)。

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

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

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

【讨论】:

  • 禁用视图封装会全局应用组件中的所有 CSS。
  • 不要使用ViewEncapsulation.None!通过使这些样式可能泄漏到其他组件中会造成很大的损害。
  • @AlexKlaus,同意,这就是我在答案中提到的原因,这并不理想。实际上,我只使用了一次将共享的可重复样式应用于 Angular Material 组件。如果您尝试禁用封装,您可能会在某个时候变得一团糟。很高兴了解此选项,但在您不确定是否需要此选项时不要使用它。
【解决方案3】:

我会强调将::ng-deep 限制为组件的唯一子级的重要性,方法是要求父级是封装的 css 类。

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

::ng-deep 之前使用:host 关键字将自动处理此问题:

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

或者,您可以通过在 ::ng-deep 关键字之前添加组件范围的 CSS 类来实现相同的行为:

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

组件模板:

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

生成的(Angular 生成的)css 将包含唯一生成的名称并仅应用于其自己的组件实例:

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

【讨论】:

  • 伙计,你的回答 my-component ::ng-deep... 拯救了我的一天。我花了一整天的时间尝试使用 ng-deep 为我的组件应用样式,并从我的整个应用程序中覆盖我的所有组件。
  • 值得注意的是:“为了将指定样式的范围限定为当前组件及其所有后代 [但不是全局],请务必在 ::ng-deep 之前包含 :host 选择器。”来自:angular.io/guide/component-styles
  • 给出准确的解释应该是公认的答案
【解决方案4】:

确保不要错过角度指南中::ng-deep 正上方的:host-context 的解释:https://angular.io/guide/component-styles。直到现在我都想念它,希望我能早点看到它。

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

例如,我设计的组件中有一个黑色的 &lt;h1&gt; 标头,我希望能够在它显示在深色主题背景上时将其更改为白色。

如果我无法访问源代码,我可能必须在父级的 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,虽然这通常是必要的,但在某种程度上是一种反模式。

在这种情况下,&amp;h1 取代(这就是 sass/scss 的工作方式),因此您可以定义您的“正常”和主题/替代 css,这非常方便。

注意获取正确的: 编号。 ::ng-deep 有两个,:host-context 只有一个。

【讨论】:

  • 如果您不想从任何父组件继承theme-dark,也可以使用:host(.theme-dark)。这将完全取决于您的网站 CSS 设计。属性也非常有用,可以单独在 css 中以复杂的方式组合:host([theme='dark']:not([dayofweek='tuesday'))
  • 另请注意,这遵循正常的 css 规则,因此,如果您在具有 .theme-light 类的容器内有如上所述的组件(带有主机上下文 css),则该组件又嵌套在带有.theme-dark 的容器仍然会拾取theme-dark 并应用css。但这对于“modernizr”类型类来说是一个很好的解决方案,或者如果你有一个全局主题集并且只有一次。
  • 我可以使用 :host-context 代替 ::ng-deep 吗?
  • @eddy 我现在太困了,无法充分考虑这一点,但 host-context 几乎就像 ng-deep 一样,但会向上而不是向下移动 DOM 树。所以它绝对不等价,但你可以
【解决方案5】:

只是更新:

您应该使用::ng-deep 而不是/deep/,这似乎已被弃用。

根据文档:

不推荐使用穿透阴影的后代组合器,支持 正在从主要浏览器和工具中删除。因此,我们计划放弃 Angular 中的支持(适用于所有 3 个 /deep/、>>> 和 ::ng-deep)。直到 那么 ::ng-deep 应该是首选,以获得更广泛的兼容性 工具。

你可以找到它here

【讨论】:

  • 在本文中明确表示 ::ng-deep 也已被弃用:“我们计划放弃对 Angular 的支持(对 /deep/、>>> 和 ::ng-deep 的所有 3 个) "。
【解决方案6】:

谨慎使用 ::ng-deep。我在整个应用程序中使用它来将材料设计工具栏颜色设置为整个应用程序中的不同颜色,只是发现当应用程序在测试时工具栏颜色会相互叠加。来发现这是因为这些样式变得全局,请参阅this article 这是一个不会渗入其他组件的有效代码解决方案。

<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');
  }

}

【讨论】:

    猜你喜欢
    • 2020-06-11
    • 2014-07-11
    • 2018-05-16
    • 1970-01-01
    • 2022-08-23
    • 1970-01-01
    • 2022-08-11
    • 2019-06-22
    • 2012-03-28
    相关资源
    最近更新 更多