【问题标题】:Using a directive to add class to host element [duplicate]使用指令将类添加到宿主元素[重复]
【发布时间】:2017-01-31 00:50:08
【问题描述】:

我目前正在学习 Angular 2。我了解如何使用 Angular Renderer 设置 ElementStyle,但现在我想使用 Renderer 方法:

setElementClass(renderElement: any, className: string, isAdd: boolean) : void

我的问题是如何将 CSS 类导入到我的属性指令中? 我必须将我的 CSS 类转换为 JSON 吗?

【问题讨论】:

  • 导入一个css类是什么意思? className 是字符串,为什么你必须加载或转换或导入 css 类?

标签: angular angular2-directives


【解决方案1】:

如何使用 Renderer 和 ElementRef 将 css 类添加到元素的示例。

@Directive({
   selector: '[whatever]'
})
class WhateverDirective {
   constructor(renderer: Renderer, el: ElementRef) {
       renderer.setElementClass(el.nativeElement, 'whatever-css-class', true);
   }
}

whatever-css-class 定义在一个 css 文件中,在 html 中引用

【讨论】:

  • 是的,绝对是,到目前为止我理解了 setElementClass 函数,但是什么是 CSS 类,属性指令没有 css 文件,或者有可能添加一个吗?跨度>
  • 对,所以你可以做的是在css文件中定义你在html中引用的类,这样它就会被应用到元素上。
  • Renderer 类现已弃用。请改用Renderer2
  • 您不需要 DI 渲染器,而是使用 @HostBinding('class.your-class') - stackoverflow.com/a/58071653/1148107
【解决方案2】:

原始 OP 询问如何使用渲染器。为了完整性,我已经包含了@HostBinding。

使用@HostBinding

要为元素添加类,您可以使用@HostBinding

import { Directive, HostBinding} from '@angular/core';

@Directive({
  selector: '[myDirective]',
})
export class MyDirective {

  @HostBinding('class')
  elementClass = 'custom-theme';

  constructor() {
  }
}

将@HostBinding 与多个类一起使用

为了让多个类使用起来更舒服,您可以使用 ES6 getter 并将这些类连接在一起,然后再返回它们:

import { Directive, HostBinding} from '@angular/core';

@Directive({
  selector: '[myDirective]',
})
export class MyDirective {
  protected _elementClass: string[] = [];

  @Input('class')
  @HostBinding('class')
  get elementClass(): string {
      return this._elementClass.join(' ');
  }
  set(val: string) {
      this._elementClass = val.split(' ');
  }

  constructor() {
      this._elementClass.push('custom-theme');
      this._elementClass.push('another-class');
  }
}

使用渲染器

更底层的 API 是 Renderer2。 Renderer2 在您想要应用到元素的动态类集时很有用。

示例:

import { Directive, ElementRef, Renderer2 } from '@angular/core';

@Directive({
  selector: '[myDirective]',
})
export class MyDirective {

  constructor(private renderer: Renderer2, hostElement: ElementRef) {
    renderer.addClass(hostElement.nativeElement, 'custom-theme');
  }
}

【讨论】:

  • 我用for循环的classes数组,实用吗?
  • 对于多个类,您应该执行一个循环。如果您查看source,您会看到Angular 调用了classList.add 方法。虽然这个原生方法支持多个参数,但 Angular 实现一次只允许传递一个类名。
  • 从构造函数推送类似乎不起作用。但它适用于 ngAfterViewInit
  • setter 似乎永远不会被调用,导致主机的任何初始类丢失:-(
  • 您不需要 DI 渲染器或操作现有类,而是使用 @HostBinding('class.your-class') - stackoverflow.com/a/58071653/1148107
【解决方案3】:

为什么要使用 Renderer 或 Renderer2 类?在指令中执行此操作的首选方法是使用 @HostBinding 装饰器。

例子:

import { HostBinding } from '@angular/core';

@Directive({
    selector: '[myDirective]'
})
export class MyDirective {

    @HostBinding('class')
    className = 'my-directive-css-class';
}

【讨论】:

  • 如果你想添加一个基于其他属性的类,这很有用,即动态:
  • 我认为这只对完全替换可能已经在 HTML 中定义的类有用。我将如何使用这种方法添加一个类?渲染器似乎更灵活。
  • 这种语法更好:@HostBinding('class.isPlaying') class_isPlaying = true;(见stackoverflow.com/a/35183074/16940)。它将切换类,而不是仅仅清除整个属性。
  • @Simon_Weaver 这种语法可能更好,如果您需要基于属性切换一个类,它仍然是一个不错的选择。然而,在最新版本的 Angular(例如 10)中,@HostBinding('class') 似乎并没有消除整个属性。它的行为就像模板中的 [class] 绑定,因为您可以将类作为空格分隔的字符串、字符串数组,甚至将条件类作为对象(但请注意,它不会检测到数组或对象)。参考:angular.io/guide/…
【解决方案4】:

这只是另一种方式,但对我来说更容易理解。

你让我知道你的想法

import { Directive, Input} from '@angular/core';

@Directive({
  selector: '[whatever]',
  host: {
    // These are like ngClass class condition values
    '[class.custom-class1]': 'true', // Default class for example
    '[class.custom-class2]': 'foo === "expectedValue"', // Predicate1
    '[class.custom-class3]': 'foo !== "expectedValue"', // Predicate2
  },
})
export class WhateverDirective {
  @Input() foo: string;
}

【讨论】:

    猜你喜欢
    • 2016-04-11
    • 2018-06-21
    • 2018-11-19
    • 2018-05-12
    • 2020-08-28
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    • 2023-04-06
    相关资源
    最近更新 更多