用什么代替:: ng-deep


99

我正在尝试对路由器插座放置的元素进行倾斜设置,以确保生成的元素的宽度为100%

从大多数答复中,我看到我应该使用::ng-deep选择器,但是从Angular的文档中,它已被弃用。有替代品::ng-deep吗?


2
::ng-deep不会去任何地方。它将始终是您可以启用的设置。没有社区的强烈反对,他们绝对不可能立即删除它。看看此搜索返回了多少结果github.com/search?q=%3A%3Ang-deep&type=Code-就像说css!important属性将消失
Simon_Weaver

我不知道-出于好奇,我在Mono-repo(多个相当大的企业应用程序)中进行了全项目搜索,结果只有69条参考。我认为这绝对是摆脱弃用的可接受的重构,并且只要他们提出替代方案,就会很乐意这样做。此外,!important在CSS规范中占有重要位置,而::deep始终只是一个建议。
dudewad

Answers:


110

FWIW在我的研究中,我没有找到ng-deep的替代品或其他适用的替代品。我相信这是因为,Angular团队正在遵循影子dom的W3C规范,该规范最初具有诸如的选择器deep。但是,W3c自此删除了该建议,但未用新建议取代它。在此之前,我想像Angular团队将继续使用::ng-deep它的替代方案,但由于W3C草案的待定状态而处于过时状态。我现在无法花时间来找到支持该文档的文档,但是最近确实看到了。

长话短说:继续使用::ng-deep它及其替代方案,直到创建替代方案为止-弃用只是一个早期通知,因此,只要实际的更改实现,人们就不会蒙蔽双眼。

-更新-

https://drafts.c​​sswg.org/css-scoping-1/ 如果您有兴趣,这是提案草案。看来他们正在为影子dom树中的元素选择器的强大集合。我认为正是这一规范(一旦获得批准)将通知角度克隆,甚至还有一个克隆(即,一旦在浏览器中发布,角度可能不需要实现自己的选择器)。


我对此表示同意,但我不建议您使用不推荐使用的框架(和浏览器)功能有目的地编写新代码。
MT_

7
我要么选择。但是没有其他选择,我认为这里没有明确列出。您有什么建议可以帮助您吗?
dudewad

1
我很快想到的唯一选择是重构组件的嵌套,这可能比您有时间的工作还要多,但可能会产生其他好处……
MT_18年

36
使用第三方库,几乎不可能避免不得不::ng-deep偶尔使用一次(如果您完全关心网站的外观),即使使用棱角分明的东西也是如此。他们有几个月无法修复的错误,解决方法通常涉及ng-deep。而且不要混淆不同的不推荐使用的“深度”选择器-::ng-deep绝对是不推荐使用的选择器。
Simon_Weaver

1
是的,这是整个系统中最难看的部分之一。但是封装就是封装。您必须通过在CSS中显式使用:: ng-deep来打破界限,或者需要以编程方式进行操作。有时我们在component标签上使用属性来指示组件处于什么“模式”(即上下文),然后样式可以通过属性选择器:host[some-context] {}(而不是:: ng-deep)存在于子组件中,例如:-取决于您想要哪种灵活性/可移植性。我不喜欢这两种方式,但这就是封装的世界。
dudewad

22

要绕开已弃用的设备::ng-deep,通常会禁用它ViewEncapsulation。尽管这不是最佳方法,但它对我很有帮助。

要禁用ViewEncapsulation,请在组件中执行以下操作:

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

@Component({
  selector: 'app-header',
  templateUrl: './header.component.html',
  styleUrls: ['./header.component.scss'],
  encapsulation: ViewEncapsulation.None
})

export class HeaderComponent {

}

这将使此组件中的.scss样式对整个应用程序都是全局的。为了不允许样式沿着父级和同级组件的链向上移动,请使用选择器将整个scss包装起来,如下所示:

app-header {
  // your styles here and any child component styles can go here
}

现在,此处指定的样式将归因于子组件,因此添加CSS时,您必须特别注意css选择器,并注意p和q(可能会添加Angular应用中指定的子选择器,然后添加其样式)。

由于上面的段落,我说这不是最好的方法,但这对我很有帮助。


12
这只是解决方法,如果您有庞大的项目,关闭电源ViewEncapsulation会使这些样式可能泄漏到所有组件中,从而造成很多损失。应当明智地使用此功能并充分理解
mpro19年

5
@mpro我了解,这就是为什么我要提出警告,并说这不是最好的方法,并且您必须注意p和q的情况,并且必须特别具体。对我来说,这种方法到目前为止效果很好。:: ng-deep被标记为弃用,这是一种解决方法。
AliF50

1
坦率地说,如果您因为威胁弃用而这样做,这是一个可怕的结论。是的,我知道您也承认这一点,但是我真的认为您是在通过这种方式射击自己。由于很多原因,视图封装非常有用。但是,这并不比不使用任何角度小组的人糟糕,没有任何合理的解决方法并导致很多混乱。归根结底,您仍在为网络浏览器编写代码,而不是某种专有的角度引擎。
Simon_Weaver

2
@Simon_Weaver我尊重您的意见,并感谢您的分享。我只是将其表面化,因为这是我用来规避过时的方法。我还浮出水面。
AliF50

4
@ AliF50“绕过绝望”并不是真的。真正的问题是,而且我一生中从未见过这种情况,因此他们在不命名的情况下就弃用了它。我的回答(上面被接受的答案)解释了我的假设,即他们为什么这样做(W3C不赞成使用)以符合规范。但是,如果您阅读了这些建议,则看起来:: ng-deep会被替换为合适的替代方法,这意味着,当可用时,您只需更新:: ng-deep引用,而不是实际需要的方法即可。重新架构整个应用程序。
dudewad

19

深层样式的简单替代方法是使用父组件的元素选择器的通用样式。因此,如果您在hero-details.component.css中具有此功能:

:host ::ng-deep h3 {
  font-style: italic;
}

它将在styles.css中变为:

app-hero-details h3 {
  font-style: italic;
}

基本上,深层样式是未封装的样式,因此从概念上讲,它对我来说更像是通用样式,而不是组件样式。我个人不再使用深样式。重大更改是主要版本更新中的正常现象,而过时的功能删除则是公平的游戏。


1
哇,我现在觉得很蠢。谢谢!来自其他前端框架,我认为这是不可能的
Rafael Vidaurre

1
这真的很有用。令人讨厌的是,:: ng-deep在没有替代的情况下被弃用了这么长时间(:host :: ng-deep可以按预期工作,但是我不想使用已弃用的东西)。
阿列克谢

8

如前所述,如果您使用的是第三方库,几乎不可能避免::ng-deep偶尔使用。但是,当::ng-deep浏览器不再支持以前的项目时,您将如何处理?

为此,我将提出以下建议:

  1. 明智地使用ViewEncapsulation。这仅转换为需要访问更深层组件的那些组件。
@Component({
      selector: 'app-example',
      templateUrl: './example.component.html',
      styleUrls: ['./example.component.scss'],
      encapsulation: ViewEncapsulation.None
    })
  1. 现在,为了避免冲突和CSS怪异,您应该(通常)总是用类包装组件的模板。因此,example.component.html应该类似于:
<section class="app-example-container">
<!-- a third party component -->
<mat-tab-group>
<mat-tab label="First"></mat-tab>
<mat-tab label="Second"></mat-tab>
</mat-tab-group>
</section>
  1. 同样,根据规则,每个单个SCSS文件的第一行将定位到组件容器。由于没有封装,您可以通过将第三方组件作为目标类来对其进行修改。就是说,example.component.scss应该像这样:
.app-example-container {
/* All the CSS code goes here */
.mat-tab-group .mat-tab-label {color: red;}
}

关于未来的自我说明:https : //angular.io/guide/component-styles
应该是寻找官方替代品/路途的第一个地方


But what are you going to do about your previous projects when the ::ng-deep became no longer supported by browsers?那不是由cli编译/多填充的,所以没有浏览器参与吗?好答案顺便说一句。
beppe9000 '20

实际将其渲染到CSS文件,然后浏览器相应地应用样式。(我认为)使用:host /deep/ .mat-tab-label它的混叠是可能的(应转换为)::ng-deep。坦白地说,使用别名似乎更方便,因为CLI可以在编译时对其进行更改,但是仍然需要ng build再次进行部署。我的解决方案是完全避免::ng-deep我所有的项目:)
guzmanoj

是的,避免重新部署
很有意义

1

这不是:: ng-deep的一般替代,而是问题作者描述的用例:

在特殊情况下,如果要设置由路由器出口插入的元素的样式,则可以使用CSS中的相邻邻居选择器来解决问题:

router-outlet+* {
  /* styling here... */
}

这将适用于所有与路由器出口直接相邻的元素。

进一步阅读:
https : //developer.mozilla.org/zh-CN/docs/Web/CSS/Adjacent_sibling_combinator
https://angular.io/guide/router#router-outlet


1
我不建议使用此选择器。似乎您正在掀起一场真正的冲突梦night,尤其是在应用程序增长时。最重要的是,*选择器实际上是CSS存在中最慢的选择器。
dudewad

@dudewad,而*选择器是最慢的选择器,它仅被应用到字面上的下一个同级(+),而不是整个链/树,因此它仅会产生名义上的差异。
埃里克·飞利浦

@ErikPhilips CSS选择器是从右到左解析的,因此这实际上是最坏的情况。
dudewad

@dudewad我想我们缺少了一些东西。 *最糟糕的情况是紧随其后,element *element + *与前两个情况相距甚远。
Erik Philips

我不知道...我还没有测试过,这只是基于我对CSS解析器如何做事情的了解。
dudewad

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.