如何将 css class 应用于由 router-outlet 创建的组件元素?
How to apply css class to a component element when it's created by router-outlet?
我有 DOM 看起来像这样:
<app>
<router-outlet></router-outlet>
<project>...</project>
</app>
其中 project
元素由路由器插入。
如何向该元素添加 class?
假设您始终希望将 class 应用于此组件,您可以在组件元数据中使用 host
:
@Component({
selector:'project',
host: {
class:'classYouWantApplied'
}
})
导致:
<app>
<router-outlet></router-outlet>
<project class="classYouWantApplied">...</project>
</app>
您可以使用相邻兄弟选择器
router-outlet + project { ... }
https://developer.mozilla.org/en/docs/Web/CSS/Adjacent_sibling_selectors
但前提是@drewmoore 的方法不适用。
关键是/deep/关键字:
:host /deep/ router-outlet + project {
display: block;
border: 10px solid black;
}
无需任何额外配置即可运行。
:host /deep/ router-outlet + *
对于由 Angular 路由器动态创建的任何组件。
2018/3/5 编辑:
因为 Angular 4.3.0 made /deep/
deprecated, its suggested alternative is ::ng-deep
. And there were a long discussion 关于这个。
如果您需要有条件地添加 class,您可以从组件中以编程方式添加它:
constructor(private renderer: Renderer2, private elemRef: ElementRef) {
if(someCondition){
renderer.addClass(elemRef.nativeElement, 'myClass');
}
}
您可以使用 HostBinding
执行此操作,这实际上与使用已经提到的 host
属性 相同,尽管该方法默认会抛出 TSLint 错误上市规则。
在您要应用的组件中 class:
import { Component, HostBinding, Host (optional for typing) } from '@angular/core';
@Component({...})
export class GiveMeAClassComponent {
@HostBinding('class.some-class') someClass: Host = true;
...
}
然后在你的根 styles.scss
文件中,你可以添加以下内容:
.some-class {
// Styles in here will now be applied to your GiveMeAClassComponent at a root level
}
<app>
<div class="your css class">
<router-outlet></router-outlet>
</div>
</app>
这对我有用
使用 adjacent sibling selector
和 *
通配符 select 紧跟在 router-outlet
之后的元素
styles.css
router-outlet + * {
/* your css */
}
目前,Angular 6 建议我使用@HostBindings 和@HostListeners 而不是主机属性:
export class ProjectComponent {
@HostBinding('class') classes = 'classYouWantApplied';
}
我创建了一个 RouterOutletHelperDirective
可以根据需要进行修改。
您的用例可能不同,但对我而言:
- 我需要在每个路由器出口生成的项目上设置一组默认的 classes
- 我需要根据某些条件防止此默认设置,例如
ActivatedRoute
数据。
你这样使用它(class 是可选的):
<router-outlet routerOutletHelper
[routerOutletHelperClass]="'blue-border'"></router-outlet>
然后创建指令,将其添加并导出到您的应用程序模块。
import { Directive, ElementRef, Renderer2, Input } from "@angular/core";
import { RouterOutlet } from "@angular/router";
import { Subscription } from "rxjs";
@Directive({
selector: 'router-outlet[routerOutletHelper]'
})
export class RouterOutletHelperDirective
{
constructor(private routerOutlet: RouterOutlet,
private element: ElementRef<HTMLElement>,
private renderer: Renderer2) { }
subscription = new Subscription();
@Input('routerOutletHelperClass')
customClassName: string | undefined;
ngOnInit()
{
this.subscription.add(this.routerOutlet.activateEvents.subscribe((_evt: any) => {
// find the component element that was just added
const componentElement = this.element.nativeElement.nextSibling;
// add a custom class
if (this.customClassName)
{
this.renderer.addClass(componentElement, this.customClassName);
}
// add my default classes, unless the activated route data
// (specified in module routing file) has { addDefaultClasses: false }
if (this.routerOutlet.activatedRouteData && this.routerOutlet.activatedRouteData.addDefaultClasses !== false)
{
// these are my application's default classes (material / theming)
// (an additional data parameter could be 'darkTheme: boolean')
this.renderer.addClass(componentElement, 'mat-typography');
this.renderer.addClass(componentElement, 'rr-theme-light');
}
}));
}
ngOnDestroy()
{
this.subscription.unsubscribe();
}
}
由于路由器在 router-outler 元素之后注入组件,
如果我们想使用同一组规则设置所有注入组件的样式,则以下规则可能会有所帮助。
css “+” 运算符 select 某种类型的第一个兄弟元素,而星号 (*) 用作 select 任何第一个兄弟元素的通配符路由器插座
router-outlet + * {
// your rules
}
对我来说,它有助于将路由器插座包装到另一个容器中。
<div class="classYouWantApplied">
<router-outlet>
</div>
像这样,您可以将 class 应用于周围的容器。
添加主机 class 名称,这将向组件添加 class,然后使用 adjacent 定位元素。
@Component({
selector:'project',
host: {
class:'Project-wrapper'
}
})
现在使用 CSS 与 angular
相邻
::ng-deep to target it:
::ng-deep .Project-wrapper {}
很简单,假设在您的应用组件中有一个
<router-outlet ></router-outlet>
在此 router-outlet 中,您有一个名为
<app-product-detail></app-product-detail>
并且您想更改 app.component.html 中的视图。
首先在组件内部 <app-product-detail>
添加此代码段:
@Component({
selector: 'app-product-detail',
host: {
class:'Project-wrapper'
},
templateUrl: './product-detail.component.html',
styleUrls: ['./product-detail.component.css']
})```
class='could be any name'
在 app.component.css 中添加以下代码段:
::ng-deep .Project-wrapper {
width: 85%;
background-color: aqua;
}
我有 DOM 看起来像这样:
<app>
<router-outlet></router-outlet>
<project>...</project>
</app>
其中 project
元素由路由器插入。
如何向该元素添加 class?
假设您始终希望将 class 应用于此组件,您可以在组件元数据中使用 host
:
@Component({
selector:'project',
host: {
class:'classYouWantApplied'
}
})
导致:
<app>
<router-outlet></router-outlet>
<project class="classYouWantApplied">...</project>
</app>
您可以使用相邻兄弟选择器
router-outlet + project { ... }
https://developer.mozilla.org/en/docs/Web/CSS/Adjacent_sibling_selectors
但前提是@drewmoore 的方法不适用。
关键是/deep/关键字:
:host /deep/ router-outlet + project {
display: block;
border: 10px solid black;
}
无需任何额外配置即可运行。
:host /deep/ router-outlet + *
对于由 Angular 路由器动态创建的任何组件。
2018/3/5 编辑:
因为 Angular 4.3.0 made /deep/
deprecated, its suggested alternative is ::ng-deep
. And there were a long discussion 关于这个。
如果您需要有条件地添加 class,您可以从组件中以编程方式添加它:
constructor(private renderer: Renderer2, private elemRef: ElementRef) {
if(someCondition){
renderer.addClass(elemRef.nativeElement, 'myClass');
}
}
您可以使用 HostBinding
执行此操作,这实际上与使用已经提到的 host
属性 相同,尽管该方法默认会抛出 TSLint 错误上市规则。
在您要应用的组件中 class:
import { Component, HostBinding, Host (optional for typing) } from '@angular/core';
@Component({...})
export class GiveMeAClassComponent {
@HostBinding('class.some-class') someClass: Host = true;
...
}
然后在你的根 styles.scss
文件中,你可以添加以下内容:
.some-class {
// Styles in here will now be applied to your GiveMeAClassComponent at a root level
}
<app>
<div class="your css class">
<router-outlet></router-outlet>
</div>
</app>
这对我有用
使用 adjacent sibling selector
和 *
通配符 select 紧跟在 router-outlet
styles.css
router-outlet + * {
/* your css */
}
目前,Angular 6 建议我使用@HostBindings 和@HostListeners 而不是主机属性:
export class ProjectComponent {
@HostBinding('class') classes = 'classYouWantApplied';
}
我创建了一个 RouterOutletHelperDirective
可以根据需要进行修改。
您的用例可能不同,但对我而言:
- 我需要在每个路由器出口生成的项目上设置一组默认的 classes
- 我需要根据某些条件防止此默认设置,例如
ActivatedRoute
数据。
你这样使用它(class 是可选的):
<router-outlet routerOutletHelper
[routerOutletHelperClass]="'blue-border'"></router-outlet>
然后创建指令,将其添加并导出到您的应用程序模块。
import { Directive, ElementRef, Renderer2, Input } from "@angular/core";
import { RouterOutlet } from "@angular/router";
import { Subscription } from "rxjs";
@Directive({
selector: 'router-outlet[routerOutletHelper]'
})
export class RouterOutletHelperDirective
{
constructor(private routerOutlet: RouterOutlet,
private element: ElementRef<HTMLElement>,
private renderer: Renderer2) { }
subscription = new Subscription();
@Input('routerOutletHelperClass')
customClassName: string | undefined;
ngOnInit()
{
this.subscription.add(this.routerOutlet.activateEvents.subscribe((_evt: any) => {
// find the component element that was just added
const componentElement = this.element.nativeElement.nextSibling;
// add a custom class
if (this.customClassName)
{
this.renderer.addClass(componentElement, this.customClassName);
}
// add my default classes, unless the activated route data
// (specified in module routing file) has { addDefaultClasses: false }
if (this.routerOutlet.activatedRouteData && this.routerOutlet.activatedRouteData.addDefaultClasses !== false)
{
// these are my application's default classes (material / theming)
// (an additional data parameter could be 'darkTheme: boolean')
this.renderer.addClass(componentElement, 'mat-typography');
this.renderer.addClass(componentElement, 'rr-theme-light');
}
}));
}
ngOnDestroy()
{
this.subscription.unsubscribe();
}
}
由于路由器在 router-outler 元素之后注入组件, 如果我们想使用同一组规则设置所有注入组件的样式,则以下规则可能会有所帮助。
css “+” 运算符 select 某种类型的第一个兄弟元素,而星号 (*) 用作 select 任何第一个兄弟元素的通配符路由器插座
router-outlet + * {
// your rules
}
对我来说,它有助于将路由器插座包装到另一个容器中。
<div class="classYouWantApplied">
<router-outlet>
</div>
像这样,您可以将 class 应用于周围的容器。
添加主机 class 名称,这将向组件添加 class,然后使用 adjacent 定位元素。
@Component({
selector:'project',
host: {
class:'Project-wrapper'
}
})
现在使用 CSS 与 angular
相邻::ng-deep to target it:
::ng-deep .Project-wrapper {}
很简单,假设在您的应用组件中有一个
<router-outlet ></router-outlet>
在此 router-outlet 中,您有一个名为
<app-product-detail></app-product-detail>
并且您想更改 app.component.html 中的视图。
首先在组件内部 <app-product-detail>
添加此代码段:
@Component({
selector: 'app-product-detail',
host: {
class:'Project-wrapper'
},
templateUrl: './product-detail.component.html',
styleUrls: ['./product-detail.component.css']
})```
class='could be any name'
在 app.component.css 中添加以下代码段:
::ng-deep .Project-wrapper {
width: 85%;
background-color: aqua;
}