了解@HostBinding如何在角度为toggleClass指令工作

时间:2017-10-30 18:49:40

标签: angular angular2-directives

我遇到了以下角度指令:

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

@Directive({
    selector: '[appDropdown]'
})

export class DropdownDirective {
    @HostBinding('class.open') isOpen = false;

    @HostListener('click') toggleOpen() {
        this.isOpen = !this.isOpen;
    }
}

在网上冲浪代码时,基本上代码只会在使用该指令的元素上切换open类,因此可以像这样使用该指令:

<ul class="nav navbar-nav navbar-right">
    <li class="dropdown" appDropdown>
        <a href="#" class="dropdown-toggle" role="button">Manage <span class="caret"></span></a>
        <ul class="dropdown-menu">
            <li><a href="#">Save Data</a></li>
            <li><a href="#">Fetch Data</a></li>
        </ul>
    </li>
</ul>

现在我不明白的是指令中的以下代码行:

 @HostBinding('class.open') isOpen = false;

究竟是什么,它究竟是如何运作的?我不太了解上面的代码行。有人可以解释一下吗?

3 个答案:

答案 0 :(得分:3)

@HostBinding允许您为指令的主机元素定义绑定。正如您可能知道的那样,special binding syntax for the class看起来像这样:

<element [class.class-name]="expression">...</element>

您可以在How [class] [attr] [style] directives work中阅读实施细节。

在您的示例中,li元素是host元素,表达式是isOpen,因此绑定引用的主机实际上定义了以下内容:

<li class="dropdown" appDropdown [class.open]="isOpen">

答案 1 :(得分:2)

看看这个link。总结一下:

@HostBinding装饰器允许您更新指令的host元素的属性。据我所知,这意味着Angular变化检测将评估由它修饰的变量(expresions)并将更改传播到您在host元素中“绑定”的属性(在您的情况下添加\ remove类)。 / p>

答案 2 :(得分:0)

小心不要在指令中将 @HostBinding Renderer2 混合以更改DOM样式。不确定原因,但会得到意想不到的结果。

以下示例:

//: WORKS: ENTER_A + EXIT_A
//: WORKS: ENTER_B + EXIT_B

//: FAILS: ENTER_A + EXIT_B
//: FAILS: ENTER_B + EXIT_A

import {
  Directive    ,

  HostBinding  ,
  HostListener ,

  Renderer2    ,
  ElementRef   } from '@angular/core';

@Directive({
  selector: '[appBetterHighlight]'
})
export class BetterHighlightDirective {

  constructor(private ER: ElementRef, private REN:Renderer2 ) {}

  changeBgColor( color_string: string ){
    this.REN.setStyle( this.ER.nativeElement, 'background-color', color_string);
  }

  //Use CamelCase because DOM does not understand "background-color"
  @HostBinding('style.backgroundColor') backgroundColor: string = "blue";

  @HostListener('mouseenter') mouseover(ED: Event){
    //this.changeBgColor( "magenta");  //<<<<<< [ ENTER_A ]
    this.backgroundColor = 'magenta';  //<<<<<< [ ENTER_B ]
    console.log("[MOUSE_ENTER]");
  }

  @HostListener('mouseleave') mouseleave(ED: Event){
    //this.changeBgColor("green"); //<<<<<<<<<< [ EXIT_A ]
    this.backgroundColor = 'green'; //<<<<< [ EXIT_B ]
    console.log("[MOUSE_LEAVE]");
  }

}