Angular 2在指令中动态添加主机侦听器

Angular 2在指令中动态添加主机侦听器,angular,Angular,我有一个在单击时打开子菜单的指令,但我想改进它,只在单击目标元素时激活文档单击。因此,问题是如何改进该指令,或者如何动态添加主机侦听器 import { Directive, HostListener, Input, AfterContentInit, ElementRef, ViewContainerRef, ContentChild } from '@angular/core'; @Directive({ selector: '[appSubMenu]' }) export cl

我有一个在单击时打开子菜单的指令,但我想改进它,只在单击目标元素时激活文档单击。因此,问题是如何改进该指令,或者如何动态添加主机侦听器

import { Directive, HostListener, Input, AfterContentInit, ElementRef, ViewContainerRef, ContentChild } from '@angular/core';

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

export class SubMenuDirective implements AfterContentInit {
    private visible: boolean = false;
    @ContentChild('subMenu') child: ElementRef;

    constructor(private vcRef: ViewContainerRef) { }

    ngAfterContentInit() {
        this.child.nativeElement.style.display = 'none';
    }

    @HostListener('document:click', ['$event', '$event.target'])
    show(event:MouseEvent, targetElem: HTMLElement): void {
        if (this.vcRef.element.nativeElement === targetElem && !this.visible) {
            this.child.nativeElement.style.display = 'block';
            this.visible = true;
        } else {
            this.child.nativeElement.style.display = 'none';
            this.visible = false;
        }
    }
}

可以使用Renderer类实现动态事件绑定。有两个功能:

  • 侦听
    :侦听元素中的事件
  • listenGlobal
    :收听全局事件,例如文档、正文
因此,在您的情况下,它将如下所示:

import{Directive,HostListener,Input,AfterContentInit,ElementRef,ViewContainerRef,ContentChild}来自“@angular/core”;
@指示({
选择器:“[appSubMenu]”
})
导出类子菜单指令实现AfterContentInit{
私有可见:布尔值=false;
私人注销:功能;
@ContentChild(“子菜单”)子菜单:ElementRef;
构造函数(私有vcRef:ViewContainerRef,私有呈现器:呈现器){}
ngAfterContentInit(){
this.child.nativeElement.style.display='none';
}
@HostListener('单击',['$event']))
元素已单击(事件:MouseEvent){
this.visible=!this.visible;
如果(这个可见){
this.unregister=this.renderer.listenGlobal('document','click',()=>{
this.child.nativeElement.style.display='none';
这个。取消注册();
});
}否则{
this.child.nativeElement.style.display='block';
}
}
}

渲染器类已从Angular 4+弃用。这是解决办法。链接: