How to style child components from parent component's CSS file?
我有一个父组件:
1 | <parent></parent> |
我想用子组件填充该组:
1 2 3 4 5 | <parent> <child></child> <child></child> <child></child> </parent> |
父模板:
1 2 | <!-- Children goes here --> <ng-content></ng-content> |
子模板:
1 | Test |
由于
在父组件中,我尝试执行以下操作:
1 2 3 | .parent .child { // Styles for child } |
但是
我尝试使用
1 2 3 4 5 | // child.component.ts styleUrls: [ './parent.component.css', './child.component.css', ] |
但这没有帮助,还尝试了另一种方法,将
那么,如何设置父组件中包含的子组件的样式?
更新-最新方式
如果可以避免,请不要这样做。正如Devon Sans在评论中指出的那样:该功能很可能已被弃用。
更新-较新的方式
从Angular 4.3.0起,不推荐使用所有可穿透的CSS组合器。 Angular团队推出了一个新的组合器
演示:https://plnkr.co/edit/RBJIszu14o4svHLQt563?p=preview
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | 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> ` |
旧方法
您可以使用
工作示例:http://plnkr.co/edit/1RBDGQ?p=preview
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | 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> ` |
更新3:
如果您对此有任何见解,请发表评论。
更新2:
由于现在不推荐使用
更新:
如果使用Angular-CLI,则需要使用
原版的:
转到Angular2的Github页面并随机搜索"样式"后,我发现了以下问题:Angular 2-innerHTML样式
据说使用了
(>>>) (and the equivalent/deep/) and ::shadow were added in 2.0.0-beta.10. They are similar to the shadow DOM CSS combinators (which are deprecated) and only work with encapsulation: ViewEncapsulation.Emulated which is the default in Angular2. They probably also work with ViewEncapsulation.None but are then only ignored because they are not necessary. These combinators are only an intermediate solution until more advanced features for cross-component styling is supported.
blockquote>
所以简单地做:
1 :host >>> .child {}在
parent 的样式表文件中解决了该问题。请注意,如以上引用所述,在支持更高级的跨组件样式之前,此解决方案只是中间的。
如果您不想使用:: ng-deep,则可以这样做,这似乎是正确的方法:
1
2
3
4
5
6 import { ViewEncapsulation } from '@angular/core';
@Component({
....
encapsulation: ViewEncapsulation.None
})然后,您可以通过:: ng-deep修改组件中的CSS形式
1
2
3
4 .mat-sort-header-container {
display:flex;
justify-content:center;
}警告:要小心,好像您的组件有很多子代一样,为此组件编写的CSS可能会影响所有子代!
可悲的是,似乎不推荐使用/ deep /选择器(至少在Chrome中)
https://www.chromestatus.com/features/6750456638341120简而言之,似乎(目前)没有长期解决方案,只能以某种方式让您的子组件动态设置样式。
您可以将样式对象传递给孩子,并通过以下方式应用它:
或者,如果您有特定的样式,则可以使用类似的内容:
与此相关的更多讨论:
https://github.com/angular/angular/issues/6511
发生了同样的问题,因此,如果您在使用scss / sass的angular2-cli时使用'/ deep /'而不是'>>>',则尚不支持最后一个选择器(但在CSS中效果很好)。
如果要比实际子组件更有针对性,则应执行以下操作。这样,如果其他子组件共享相同的类名,则它们不会受到影响。
柱塞:
例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74 import {Component, NgModule } from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'
@Component({
selector: 'my-app',
template: `
I'm the host parent
<child-component class="target1"></child-component><br/>
<child-component class="target2"></child-component><br/>
<child-component class="target3"></child-component><br/>
<child-component class="target4"></child-component><br/>
<child-component></child-component><br/>
`,
styles: [`
/deep/ child-component.target1 .child-box {
color: red !important;
border: 10px solid red !important;
}
/deep/ child-component.target2 .child-box {
color: purple !important;
border: 10px solid purple !important;
}
/deep/ child-component.target3 .child-box {
color: orange !important;
border: 10px solid orange !important;
}
/* this won't work because the target component is spelled incorrectly */
/deep/ xxxxchild-component.target4 .child-box {
color: orange !important;
border: 10px solid orange !important;
}
/* this will affect any component that has a class name called .child-box */
/deep/ .child-box {
color: blue !important;
border: 10px solid blue !important;
}
`]
})
export class App {
}
@Component({
selector: 'child-component',
template: `
Child: This is some text in a box
`,
styles: [`
.child-box {
color: green;
border: 1px solid green;
}
`]
})
export class ChildComponent {
}
@NgModule({
imports: [ BrowserModule ],
declarations: [ App, ChildComponent ],
bootstrap: [ App ]
})
export class AppModule {}希望这可以帮助!
码矩阵
在Angular中有一些实现此目的的选项:
1)您可以使用深CSS选择器
1
2
3 :host >>> .childrens {
color: red;
}2)您也可以更改视图封装,将其默认设置为"模拟",但可以轻松更改为使用Shadow DOM本机浏览器实现的本机,您只需要禁用它即可
例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 import { Component, ViewEncapsulation } from '@angular/core';
@Component({
selector: 'parent',
styles: [`
.first {
color:blue;
}
.second {
color:red;
}
`],
template: `
<child class="first">First</child>
<child class="second">Second</child>
`,
encapsulation: ViewEncapsulation.None,
})
export class ParentComponent {
constructor() {
}
}
实际上,还有另一种选择。这比较安全。您可以使用ViewEncapsulation.None但不会将所有组件样式放入其标签(也称为选择器)中。但是无论如何,总是喜欢一些全局样式以及封装样式。
这是修改后的Denis Rybalka示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 import { Component, ViewEncapsulation } from '@angular/core';
@Component({
selector: 'parent',
styles: [`
parent {
.first {
color:blue;
}
.second {
color:red;
}
}
`],
template: `
<child class="first">First</child>
<child class="second">Second</child>
`,
encapsulation: ViewEncapsulation.None,
})
export class ParentComponent {
constructor() { }
}
您不应该为父组件中的子组件元素编写CSS规则,因为Angular组件是一个独立的实体,应明确声明外部可用的内容。如果将来子布局发生更改,散布在其他组件的SCSS文件中的该子组件元素的样式可能会轻易中断,从而使您的样式非常脆弱。对于CSS,这就是
ViewEncapsulation 的目的。否则,如果您可以将值分配给面向对象编程中任何其他类的某个类的私有字段,则将是相同的。因此,您应该做的是定义可以应用于子级宿主元素的一组类,并实现子级对它们的响应方式。
从技术上讲,可以按照以下步骤进行:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 // 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>换句话说,您可以使用Angular + CSS类集提供的
:host 伪选择器在子组件本身中定义可能的子样式。然后,您可以通过将预定义的类应用于宿主元素来从外部触发这些样式。
我发现如果可以访问子组件代码,则传递@INPUT变量会更干净:
这个想法是,父母告诉孩子其外表状态应该是什么,然后孩子决定如何显示状态。这是一个不错的架构
SCSS方式:
1
2
3
4
5 .active {
::ng-deep md-list-item {
background-color: #eee;
}
}更好的方法:-使用
selected 变量:
1
2
3
4
5
6
7
8
9
10
11 <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>
</md-list>
我也有这个问题,不想使用过时的解决方案
所以我最终得到了:同时
1
2
3
4 <dynamic-table
ContainerCustomStyle='width: 400px;'
>
</dynamic-Table>子组件
1 @Input() ContainerCustomStyle: string;在html div中的子项中
1
2 <div class="container mat-elevation-z8"
[style]='GetStyle(ContainerCustomStyle)' >和在代码中
1
2
3
4
5
6 constructor(private sanitizer: DomSanitizer) { }
GetStyle(c) {
if (isNullOrUndefined(c)) { return null; }
return this.sanitizer.bypassSecurityTrustStyle(c);
}像预期的那样工作,不应弃用;)
快速的答案是,您根本不应该这样做。它破坏了组件的封装,并破坏了您从独立组件获得的收益。考虑将prop标志传递给子组件,然后如果需要,它可以自行决定如何进行不同的呈现或应用不同的CSS。
1
2
3 <parent>
<child [foo]="bar"></child>
</parent>Angular不赞成从父母那里影响孩子风格的所有方式。
https://angular.io/guide/component-styles#deprecated-deep--and-ng-deep
我已经在Angular之外解决了。我已经定义了要导入到我的孩子们的共享scss。
共享的
1
2
3
4
5
6 %cell {
color: #333333;
background: #eee;
font-size: 13px;
font-weight: 600;
}child.scss
1
2
3
4 @import 'styles.scss';
.cell {
@extend %cell;
}我提出的方法是一种解决OP所问问题的方法。正如我多次提到的,:: ng-deep,:ng-host将会被弃用,并且禁用封装在我看来是太多的代码泄漏。
我提出了一个示例,以使其更加清晰,因为angular.io/guide/component-styles指出:
The shadow-piercing descendant combinator is deprecated and support is being removed from major browsers and tools. As such we plan to drop support in Angular (for all 3 of /deep/, >>> and ::ng-deep). Until then ::ng-deep should be preferred for a broader compatibility with the tools.
如果需要,在
app.component.scss 上导入*.scss 。_colors.scss 具有一些常见的颜色值:
1
2 $button_ripple_red: #A41E34;
$button_ripple_white_text: #FFF;将规则应用于所有组件
具有
btn-red 类的所有按钮将被设置样式。
1
2
3
4
5
6
7 @import `./theme/sass/_colors`;
// red background and white text
:host /deep/ button.red-btn {
color: $button_ripple_white_text;
background: $button_ripple_red;
}将规则应用于单个组件
在
app-login 组件上具有btn-red 类的所有按钮将被设置样式。
1
2
3
4
5
6 @import `./theme/sass/_colors`;
/deep/ app-login button.red-btn {
color: $button_ripple_white_text;
background: $button_ripple_red;
}