如何将“类”添加到宿主元素?

Posted

技术标签:

【中文标题】如何将“类”添加到宿主元素?【英文标题】:How to add "class" to host element? 【发布时间】:2016-04-11 00:35:41 【问题描述】:

我不知道如何在我的组件<component></component> 中添加一个动态的class 属性,但在模板html (component.html) 中。

我找到的唯一解决方案是通过“ElementRef”原生元素修改项目。这个解决方案似乎有点复杂,做一些应该很简单的事情。

另一个问题是 CSS 必须在组件范围之外定义,破坏了组件封装。

有没有更简单的解决方案?模板中的 <root [class]="..."> .... </ root> 之类的东西。

【问题讨论】:

【参考方案1】:

这就是我所做的:

import  Component, Attribute, HostBinding  from "@angular/core";

@Component(
    selector: "selector-el",
    template: ...                                            
)
export class MyComponent 
    @HostBinding('class') get classAttribute(): string 
        let defaultClasses = 'selector-el-class';
        return defaultClasses + ' ' + this.classNames;
    

    constructor(
        @Attribute('class') public classNames: string
    )  

【讨论】:

您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center。【参考方案2】:

除了@JoshuaDavid 的回答,还有另一种定义静态类的方法,当我尝试时它适用于角度 v8(可能也适用于旧版本):

@Component(
selector: "my-component.someClass1.someClass2",
...
)

这将产生以下输出:

<my-component class="someClass1 someClass2">
 ...
</my-component>

你也可以这样使用:

@Component(
selector: ".someClass1.someClass2",
...
)

这将产生以下输出:

<div class="someClass1 someClass2">
 ...
</div>

【讨论】:

如果我指定selector: "my-component.someClass1.someClass2",,那么我必须在 HTML 中使用选择器,例如 ...【参考方案3】:

这样你就不需要在组件之外添加CSS了:

@Component(
   selector: 'body',
   template: 'app-element',
   // prefer decorators (see below)
   // host:     '[class.someClass]':'someField'
)
export class App implements OnInit 
  constructor(private cdRef:ChangeDetectorRef) 
  
  someField: boolean = false;
  // alternatively also the host parameter in the @Component()` decorator can be used
  @HostBinding('class.someClass') someField: boolean = false;

  ngOnInit() 
    this.someField = true; // set class `someClass` on `<body>`
    //this.cdRef.detectChanges(); 
  

Plunker example

这个 CSS 是在组件内部定义的,只有当 someClass 类设置在宿主元素上时才会应用选择器(从外部):

:host(.someClass) 
  background-color: red;

【讨论】:

我必须在ngOnInit()-方法中使用someField = true 而不是ngAfterViewInit()。否则我无法让它工作。 Made a fork here 显示实际的:host 部分工作。我在哪里可以了解更多关于 @Component() 装饰器中的主机参数(语法对我来说并不明显,以及 @Component documentation doesn't explain very much)或了解更多关于您首选的 HostBinding(它只是 Angular2 站点上的 listed as an Interface?) 我不知道更好的文档,但这只是用 @Input() @Output() @HostBinding() @HostListener() @ViewChild(ren)() @ContentChild(ren)() 做的另一种方式> 对主机绑定使用不同名称的getter,返回反转值@HostBinding('class.xxx') get xxxclass() return !this.someField; @YochaiAkoka 不确定您指的是什么。我不知道这个规则。少即是多,所以如果你能避免添加额外的元素,那么你应该避免它。【参考方案4】:

另一个问题是 CSS 必须在组件范围之外定义,破坏了组件封装

这不是真的。使用 scss (SASS),您可以轻松地设置组件(本身;主机)的样式:

:host 
    display: block;
    position: absolute;
    width: 100%;
    height: 100%;
    pointer-events: none;
    visibility: hidden;

    &.someClass 
        visibility: visible;
    

这样封装是“完整的”。

【讨论】:

由于其他答案有不同的方式为您的组件设置类,如果您使用这种方式,您可以将您的类设置为组件上的类。因此,对于此答案中的示例,它将是: 【参考方案5】:

对于多类的情况,就像上面提到的@jbojcic,你可以使用:

主机:类:'A B C'

【讨论】:

【参考方案6】:

您可以在 @Component 类中简单地添加@HostBinding('class') class = 'someClass';

例子:

@Component(
   selector: 'body',
   template: 'app-element'       
)
export class App implements OnInit 

  @HostBinding('class') class = 'someClass';

  constructor()       

  ngOnInit() 

【讨论】:

className directive 也可以使用,最好避免使用class 作为变量名(因为您可能会引用它并在以后更改它)。示例:@HostBinding('className') myTheme = 'theme-dark';. 我肯定会避免将变量命名为“类”。一些包将其命名为“klass”或“cssClass”【参考方案7】:

如果你想为你的宿主元素添加一个动态类,你可以将你的 HostBinding 与一个 getter 结合起来

@HostBinding('class') get class() 
    return aComponentVariable

Stackblitz 演示,https://stackblitz.com/edit/angular-dynamic-hostbinding

【讨论】:

【参考方案8】:

Günter 的回答很棒(问题是要求 dynamic 类属性),但我想我只是为了完整性而添加...

如果您正在寻找一种快速而简洁的方法来将一个或多个 static 类添加到组件的宿主元素(即,出于主题样式目的),您可以这样做:

@Component(
   selector: 'my-component',
   template: 'app-element',
   host: 'class': 'someClass1'
)
export class App implements OnInit 
...

如果你在 entry 标签上使用了一个类,Angular 会合并这些类,即,

<my-component class="someClass2">
  I have both someClass1 & someClass2 applied to me
</my-component>

【讨论】:

为了简单起见喜欢这个。但是在我的情况下,主机元素被封装了一个不同的属性,我们称它为ngcontent_host,而不是我的组件的模板, let's call those ngcontent_template, so if I put a style in the styleUrls`中的元素上的任何属性,它们不会影响主机元素,因为它们不会影响 ngcontent_host ,它们只能影响模板元素;它们只能影响ngcontent_template。我弄错了吗?对此有何建议?我想我总是可以转ViewEncapsulation.None 另一种方法是跳过变量@HostBinding('class.someClass') true;。您甚至可以从您的组件扩展的任何类中执行此操作。 添加多个类你可以做 host: '[class]': '"class1 class2"' 如果您使用主机: 变体,您可能希望在tslint.json 中将use-host-property-decorator 设置设置为false。否则,您将收到 IDE 警告。 @adamdport 该方法不起作用(不再)。在我们的应用中使用 Angular 5.2.2。 @adamdport 您的回答将创建一个名为“true”的变量,类型为“any”。不确定这是否是您的意图?【参考方案9】:

我是这样做的(Angular 7):

在组件中,添加一个输入:

@Input() componentClass: string = '';

然后在组件的 HTML 模板中添加如下内容:

<div [ngClass]="componentClass">...</div>

最后在您实例化组件的 HTML 模板中:

<root componentClass="someclass someotherclass">...</root>

免责声明:我对 Angular 还很陌生,所以我可能只是在这里走运!

【讨论】:

以上是关于如何将“类”添加到宿主元素?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 @hostbinding 为 Angular 2 中的宿主元素提供类

如何将类添加到由 appendChild 创建的元素 [重复]

如何将动态 TailwindCSS 类添加到 React 中的 DOM 元素

WordPress菜单如何将一个类添加到仅父元素?

jQuery如何以很小的延迟将一个类一个一个地添加到一个元素中?

如何将特定类添加到 select2 放置元素?