我有一个父组件:
<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>
由于父组件和子组件是两个独立的组件,它们的样式被锁定在自己的范围内。
在我的父组件中,我尝试这样做:
.parent .child {
// Styles for child
}
但是.child样式没有应用到子组件。
我尝试使用styleUrls将父组件的样式表包含到子组件中,以解决范围问题:
// child.component.ts
styleUrls: [
'./parent.component.css',
'./child.component.css',
]
但这并没有帮助,我还尝试了另一种方法,将子样式表取到父样式表中,但这也没有帮助。
那么,如何样式包含在父组件中的子组件呢?
You should not write CSS rules for a child component elements in a parent component, since an Angular component is a self-contained entity which should explicitly declare what is available for the outside world. If child layout changes in the future, your styles for that child component elements scattered across other components' SCSS files could easily break, thus making your styling very fragile. That's what ViewEncapsulation is for in the case of CSS. Otherwise, it would be the same if you could assign values to private fields of some class from any other class in Object Oriented Programming.
因此,您应该做的是定义一组可以应用于子宿主元素的类,并实现子宿主如何响应它们。
技术上可以这样做:
// 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伪选择器在子组件本身定义可能的子样式。然后,通过将预定义的类应用到<child>宿主元素,就可以从外部触发这些样式。
截至目前(Angular 9), Angular使用Shadow DOM将组件显示为自定义HTML元素。为这些自定义元素设置样式的一种优雅方法可能是使用自定义CSS变量。下面是一个通用的例子:
class ChildElement extends HTMLElement {
constructor() {
super();
var shadow = this.attachShadow({mode: 'open'});
var wrapper = document.createElement('div');
wrapper.setAttribute('class', 'wrapper');
// Create some CSS to apply to the shadow dom
var style = document.createElement('style');
style.textContent = `
/* Here we define the default value for the variable --background-clr */
:host {
--background-clr: green;
}
.wrapper {
width: 100px;
height: 100px;
background-color: var(--background-clr);
border: 1px solid red;
}
`;
shadow.appendChild(style);
shadow.appendChild(wrapper);
}
}
// Define the new element
customElements.define('child-element', ChildElement);
/* CSS CODE */
/* This element is referred as :host from the point of view of the custom element. Commenting out this CSS will result in the background to be green, as defined in the custom element */
child-element {
--background-clr: yellow;
}
<div>
<child-element></child-element>
</div>
从上面的代码中可以看到,我们创建了一个自定义元素,就像Angular为每个组件所做的那样,然后我们从全局作用域覆盖自定义元素阴影根中的背景颜色变量。
在Angular应用中,这可能是这样的:
parent.component.scss
child-element {
--background-clr: yellow;
}
child-element.component.scss
:host {
--background-clr: green;
}
.wrapper {
width: 100px;
height: 100px;
background-color: var(--background-clr);
border: 1px solid red;
}
我发现如果你可以访问子组件代码,传递@INPUT变量会更简洁:
这个想法是,父进程告诉子进程它的外观状态应该是什么,而子进程决定如何显示这个状态。这是一个很好的建筑
SCSS道:
.active {
::ng-deep md-list-item {
background-color: #eee;
}
}
更好的方法:-使用选定的变量:
<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>
如果您希望更针对实际的子组件,则应该执行以下操作。这样,如果其他子组件共享相同的类名,它们也不会受到影响。
砰砰作响:
https://plnkr.co/edit/ooBRp3ROk6fbWPuToytO?p=preview
例如:
import {Component, NgModule } from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'
@Component({
selector: 'my-app',
template: `
<div>
<h2>I'm the host parent</h2>
<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/>
</div>
`,
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: `
<div class="child-box">
Child: This is some text in a box
</div>
`,
styles: [`
.child-box {
color: green;
border: 1px solid green;
}
`]
})
export class ChildComponent {
}
@NgModule({
imports: [ BrowserModule ],
declarations: [ App, ChildComponent ],
bootstrap: [ App ]
})
export class AppModule {}
希望这能有所帮助!
codematrix