如何从父组件的CSS文件设置子组件的样式?

CSS

蛋蛋

2020-03-24

我有一个父组件:

<parent></parent>

我想用子组件填充该组:

<parent>
  <child></child>
  <child></child>
  <child></child>
</parent>

父模板:

<div class="parent">
  <!-- Children goes here -->
  <ng-content></ng-content>
</div>

子模板:

<div class="child">Test</div>

由于parentchild是两个独立的组件,因此它们的样式被锁定在自己的范围内。

在我的父组件中,我尝试执行以下操作:

.parent .child {
  // Styles for child
}

但是.child样式没有被应用到child组件。

我尝试使用styleUrlsparent的样式表包含child组件中来解决范围问题:

// child.component.ts
styleUrls: [
  './parent.component.css',
  './child.component.css',
]

但这无济于事,还尝试了另一种方法,即将child样式表提取到其中,parent但这也无济于事。

那么,如何设置父组件中包含的子组件的样式?

第3497篇《如何从父组件的CSS文件设置子组件的样式?》来自Winter(https://github.com/aiyld/aiyld.github.io)的站点

8个回答
宝儿 2020.03.24

我提出了一个示例,以使其更加清晰,因为angular.io/guide/component-styles指出:

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

在上app.component.scss*.scss根据需要导入_colors.scss具有一些常见的颜色值:

$button_ripple_red: #A41E34;
$button_ripple_white_text: #FFF;

将规则应用于所有组件

所有具有btn-red的按钮将被设置样式。

@import `./theme/sass/_colors`;

// red background and white text
:host /deep/ button.red-btn {
    color: $button_ripple_white_text;
    background: $button_ripple_red;
}

将规则应用于单个组件

所有btn-redapp-login组件具有的按钮将被设置样式。

@import `./theme/sass/_colors`;

/deep/ app-login button.red-btn {
    color: $button_ripple_white_text;
    background: $button_ripple_red;
}
凯西里 2020.03.24

随着互联网的更新,我遇到了一个解决方案。

首先要注意。

  1. 还是不要做。为了澄清,我不会计划允许您设置子组件样式的子组件。SOC。如果您作为组件设计者希望允许这样做,那么您将获得更大的权力。
  2. 如果您的孩子不住在暗影之屋,那么这对您不起作用。
  3. 如果您必须支持没有影子dom的浏览器,那么这对您也不起作用。

首先,将子组件的封装标记为阴影,以使其在实际的阴影dom中呈现。其次,将part属性添加到希望允许父元素样式化的元素上。在父母的组件样式表中,您可以使用:: part()方法访问

飞云神奇 2020.03.24

我发现如果可以访问子组件代码,则传递@INPUT变量会更干净

这个想法是,父母告诉孩子其外表状态应该是什么,然后孩子决定如何显示状态。这是一个不错的架构

SCSS方式:

.active {
  ::ng-deep md-list-item {
    background-color: #eee;
  }
}

更好的方法: -使用selected变量:

<md-list>
    <a
            *ngFor="let convo of conversations"
            routerLink="/conversations/{{convo.id}}/messages"
            #rla="routerLinkActive"
            routerLinkActive="active">
        <app-conversation
                [selected]="rla.isActive"
                [convo]="convo"></app-conversation>
    </a>
</md-list>
路易村村 2020.03.24

快速的答案是,您根本不应该这样做。它破坏了组件的封装,并破坏了您从独立组件获得的收益。考虑将prop标志传递给子组件,然后如果需要,它可以自行决定如何进行不同的呈现或应用不同的CSS。

<parent>
  <child [foo]="bar"></child>
</parent>

Angular不赞成从父母那里影响孩子风格的所有方式。

https://angular.io/guide/component-styles#deprecated-deep--and-ng-deep

蛋蛋 2020.03.24

您不应该为父组件中的子组件元素编写CSS规则,因为Angular组件是一个独立的实体,应该明确声明外部可用的内容。如果将来子布局发生更改,散布在其他组件的SCSS文件中的该子组件元素的样式可能会轻易中断,从而使您的样式非常脆弱。ViewEncapsulation就是CSS的目的。否则,如果您可以将值分配给面向对象编程中任何其他类的某个类的私有字段,则将是相同的。

因此,您应该做的是定义可以应用于子级宿主元素的一组类,并实现子级对它们的响应方式。

从技术上讲,可以按照以下步骤进行:

// child.component.html:
<span class="label-1"></span>

// child.component.scss:
:host.child-color-black {
    .label-1 {
        color: black;
    }
}

:host.child-color-blue {
    .label-1 {
        color: blue ;
    }
}

// parent.component.html:
<child class="child-color-black"></child>
<child class="child-color-blue"></child>

换句话说,您可以使用:hostAngular + CSS类集提供的伪选择器在子组件本身中定义可能的子样式。然后,您可以通过将预定义的类应用于<child>宿主元素来从外部触发这些样式

西里达蒙 2020.03.24

更新3:

::ng-deep也已弃用,这意味着您不再应该这样做。目前尚不清楚这会如何影响需要从父组件覆盖子组件中的样式的事物。对我来说,如果将其完全删除似乎很奇怪,因为这将如何影响需要替换库组件中样式的库?

如果您对此有任何见解,请发表评论。

更新2:

从那时起/deep/,所有其他阴影穿刺选择器均已弃用。Angular掉落了::ng-deep,应该使用它来获得更大的兼容性。

更新:

如果使用Angular-CLI,则需要使用/deep/代替,>>>否则它将不起作用。

原版的:

转到Angular2的Github页面并随机搜索“样式”后,我发现了以下问题:Angular 2-innerHTML样式

表示使用2.0.0-beta.10>>>::shadow选择器中添加的内容。

在2.0.0-beta.10中添加了(>>>)(以及等效的/ deep /)和:: shadow。它们类似于影子DOM CSS组合器(已弃用),仅与封装一起使用:ViewEncapsulation.Emulated,它是Angular2中的默认设置。它们可能也可以与ViewEncapsulation.None一起使用,但由于没有必要,因此仅被忽略。在支持跨组件样式的更高级功能之前,这些组合器只是一个中间解决方案。

所以简单地做:

:host >>> .child {}

parent的样式表文件中解决了此问题。请注意,如以上引用所述,在支持更高级的跨组件样式之前,此解决方案只是中间的。

小宇宙 2020.03.24

可悲的是/ deep /选择器似乎已被弃用(至少在Chrome中是这样) https://www.chromestatus.com/features/6750456638341120

简而言之,似乎(目前)没有长期解决方案,只能以某种方式让您的子组件动态设置样式。

您可以将样式对象传递给您的孩子,并通过以下方式应用该对象:
<div [attr.style]="styleobject">

或者,如果您有特定的样式,则可以使用以下方法:
<div [style.background-color]="colorvar">

与此相关的更多讨论:https : //github.com/angular/angular/issues/6511

达蒙阳光 2020.03.24

更新-最新方式

如果可以避免,请不要这样做。正如Devon Sans在评论中指出的那样:该功能很可能已被弃用。

更新-较新的方式

Angular 4.3.0开始,不再推荐使用所有可穿透的CSS组合器。Angular团队推出了一种新的组合器::ng-deep (仍然处于实验水平,而不是完整的最终方法),如下所示,

演示:https : //plnkr.co/edit/RBJIszu14o4svHLQt563? p =preview

styles: [
    `
     :host { color: red; }

     :host ::ng-deep parent {
       color:blue;
     }
     :host ::ng-deep child{
       color:orange;
     }
     :host ::ng-deep child.class1 {
       color:yellow;
     }
     :host ::ng-deep child.class2{
       color:pink;
     }
    `
],



template: `
      Angular2                                //red
      <parent>                                //blue
          <child></child>                     //orange
          <child class="class1"></child>      //yellow
          <child class="class2"></child>      //pink
      </parent>      
    `


旧方法

您可以使用encapsulation mode和/或piercing CSS combinators >>>, /deep/ and ::shadow

工作示例:http : //plnkr.co/edit/1RBDGQ?p=preview

styles: [
    `
     :host { color: red; }
     :host >>> parent {
       color:blue;
     }
     :host >>> child{
       color:orange;
     }
     :host >>> child.class1 {
       color:yellow;
     }
     :host >>> child.class2{
       color:pink;
     }
    `
    ],

template: `
  Angular2                                //red
  <parent>                                //blue
      <child></child>                     //orange
      <child class="class1"></child>      //yellow
      <child class="class2"></child>      //pink
  </parent>      
`

问题类别

JavaScript Ckeditor Python Webpack TypeScript Vue.js React.js ExpressJS KoaJS CSS Node.js HTML Django 单元测试 PHP Asp.net jQuery Bootstrap IOS Android