这个 Angular 2 自定义指令究竟是如何工作的?

How exactly works this Angular 2 custom directive?

我是 Angular 2 的新手,我正在学习有关如何创建自定义指令的教程,但我对它的确切工作方式有些疑问。

我会尽力解释它做了什么。

我有一个视图包含这样的内容:

<div class="row">
  <div class="col-xs-12">
    <div
      class="btn-group"
      appDropDown
     >
      <button
        type="button"
        class="btn btn-primary dropdown-toggle">Manage Recipe <span class="caret"></span>
      </button>

      <ul class="dropdown-menu">
        <li><a href="#">To Shopping List</a></li>
        <li><a href="#">Edit Recipe</a></li>
        <li><a href="#">Delete Recipe</a></li>
      </ul>
    </div>
  </div>
</div>

如你所见dive class btn-group 设置了我的自定义 appDropDown

<div
    class="btn-group"
    appDropDown
>

点击内部按钮时,此自定义指令只需将 open class 添加到此 div (因此 UL 内容显示为 BootStrap).

这是我的自定义指令的代码:

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

@Directive({
  selector: '[appDropDown]'
})
export class DropDownDirective {

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

  // listen to a click event:
  @HostListener('click') toggleOpen() {
    this.isOpen = !this.isOpen;
  }

}

据我所知,该指令以这种方式工作:

1) 这一行:

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

isOpen 变量绑定到我的 div 的 class.open 属性的值应用自定义指令。

所以这应该意味着如果这个 dive 有 open class 设置值将为 true,否则将为 false。

这个解释正确吗?

2) 这种方法:

// listen to a click event:
@HostListener('click') toggleOpen() {
  this.isOpen = !this.isOpen;
}

当用户在视图中单击此按钮时执行:

  <button
    type="button"
    class="btn btn-primary dropdown-toggle">Manage Recipe <span class="caret"></span>
  </button>

好吧,现在我的疑问是:为什么这个方法只在我点击这个特定按钮时执行,而不是在我页面中的任何其他按钮被点击时执行?

So it should mean that if this dive have the open class setted the value will be true, otherwise will be false.

其实恰恰相反。如果 属性 isOpen 为真,则 class open 将添加到 div。如果为假 - 已删除。

is performed when the user click this button in the view:

实际上,当您点击作为您应用指令的元素的子元素的任何元素时,它将被触发,因为本机事件冒泡。

如果要具体检查 button,请使用以下代码:

  @HostListener('click', ['$event.target'])
  clicked(element) {
    if (element.classList.contains('dropdown-toggle')) {
      console.log('button clicked');
    }
  }