2017-04-27 38 views
0

我做了一個指令,使下拉菜單在我的頭文件上工作。現在我正在使用vanilla JavaScript方式,而不是在@Directive裝飾器上使用hostListeners屬性。代碼用於工作,直到我將函數重構爲自己的函數而不是匿名函數。當重構函數時使用addEventListener時,Angular指令會產生錯誤

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

@Directive({ 
    selector: '[headerDropdown]' 
}) 
export class HeaderDropdownDirective implements OnInit, OnDestroy { 

    private isActive: boolean; 
    private isAbove: boolean; 

    private dropDownElement: Element; 
    private downArrowElement: Element; 

    constructor(private elementRef: ElementRef) { } 

    ngOnInit() { 
     this.dropDownElement = document.querySelector('.header__dropdown'); 
     this.downArrowElement = this.elementRef.nativeElement; 

     this.downArrowElement.addEventListener('mouseenter', this.downArrowOnMouseEnter); 
     this.downArrowElement.addEventListener('mouseleave', this.downArrowOnMouseLeave); 
     this.downArrowElement.addEventListener('click', this.downArrowOnClick); 
     document.addEventListener('click', this.documentOnClick); 
    } 

    ngOnDestroy() { 
     // TODO: removeEventListener 
    } 

    private activate() { 
     this.isActive = true; 
     this.downArrowElement.classList.add('header__item--active'); 
     this.dropDownElement.classList.add('header__dropdown--active'); 
    } 

    private deActivate() { 
     this.isActive = false; 
     this.downArrowElement.classList.remove('header__item--active'); 
     this.dropDownElement.classList.remove('header__dropdown--active'); 
    } 

    private downArrowOnMouseEnter() { 
     this.isAbove = true; 
    } 

    private downArrowOnMouseLeave() { 
     this.isAbove = false; 
    } 

    private downArrowOnClick() { 
     if (!this.isActive) { 
      this.activate(); 
     } else { 
      this.deActivate(); 
     } 
    } 

    private documentOnClick() { 
     if (!this.isAbove) { 
      this.deActivate(); 
     } 
    } 

} 

當我點擊或只是與DownArrow中文按鈕交互我得到的錯誤:

EXCEPTION: this.activate is not a function 
ErrorHandler.handleError @ VM12616:55 
next @ VM12615:374 
schedulerFn @ VM12630:100 
SafeSubscriber.__tryOrUnsub @ VM12634:236 
SafeSubscriber.next @ VM12634:185 
Subscriber._next @ VM12634:125 
Subscriber.next @ VM12634:89 
Subject.next @ VM12631:55 
EventEmitter.emit @ VM12630:86 
NgZone.triggerError @ VM12629:335 
onHandleError @ VM12629:296 
ZoneDelegate.handleError @ zone.js?fad3:246 
Zone.runTask @ zone.js?fad3:154 
ZoneTask.invoke @ zone.js?fad3:345 
VM12616:60 ORIGINAL STACKTRACE: 
ErrorHandler.handleError @ VM12616:60 
next @ VM12615:374 
schedulerFn @ VM12630:100 
SafeSubscriber.__tryOrUnsub @ VM12634:236 
SafeSubscriber.next @ VM12634:185 
Subscriber._next @ VM12634:125 
Subscriber.next @ VM12634:89 
Subject.next @ VM12631:55 
EventEmitter.emit @ VM12630:86 
NgZone.triggerError @ VM12629:335 
onHandleError @ VM12629:296 
ZoneDelegate.handleError @ zone.js?fad3:246 
Zone.runTask @ zone.js?fad3:154 
ZoneTask.invoke @ zone.js?fad3:345 
VM12616:61 TypeError: this.activate is not a function 
    at HTMLDivElement.HeaderDropdownDirective.downArrowOnClick (eval at <anonymous> (main.js:3477), <anonymous>:49:18) 
    at ZoneDelegate.invokeTask (eval at <anonymous> (main.js:5060), <anonymous>:275:35) 
    at Object.onInvokeTask (eval at <anonymous> (main.js:1076), <anonymous>:266:37) 
    at ZoneDelegate.invokeTask (eval at <anonymous> (main.js:5060), <anonymous>:274:40) 
    at Zone.runTask (eval at <anonymous> (main.js:5060), <anonymous>:151:47) 
    at HTMLDivElement.ZoneTask.invoke (eval at <anonymous> (main.js:5060), <anonymous>:345:33) 
ErrorHandler.handleError @ VM12616:61 
next @ VM12615:374 
schedulerFn @ VM12630:100 
SafeSubscriber.__tryOrUnsub @ VM12634:236 
SafeSubscriber.next @ VM12634:185 
Subscriber._next @ VM12634:125 
Subscriber.next @ VM12634:89 
Subject.next @ VM12631:55 
EventEmitter.emit @ VM12630:86 
NgZone.triggerError @ VM12629:335 
onHandleError @ VM12629:296 
ZoneDelegate.handleError @ zone.js?fad3:246 
Zone.runTask @ zone.js?fad3:154 
ZoneTask.invoke @ zone.js?fad3:345 
VM12634:240 Uncaught TypeError: this.activate is not a function 
    at HTMLDivElement.HeaderDropdownDirective.downArrowOnClick (eval at <anonymous> (main.js:3477), <anonymous>:49:18) 
    at ZoneDelegate.invokeTask (eval at <anonymous> (main.js:5060), <anonymous>:275:35) 
    at Object.onInvokeTask (eval at <anonymous> (main.js:1076), <anonymous>:266:37) 
    at ZoneDelegate.invokeTask (eval at <anonymous> (main.js:5060), <anonymous>:274:40) 
    at Zone.runTask (eval at <anonymous> (main.js:5060), <anonymous>:151:47) 
    at HTMLDivElement.ZoneTask.invoke (eval at <anonymous> (main.js:5060), <anonymous>:345:33) 

但如果我更改代碼到這一點,那麼它的工作原理:

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

@Directive({ 
    selector: '[headerDropdown]' 
}) 
export class HeaderDropdownDirective implements OnInit, OnDestroy { 

    private isActive: boolean; 
    private isAbove: boolean; 

    private dropDownElement: Element; 
    private downArrowElement: Element; 

    constructor(private elementRef: ElementRef) { } 

    ngOnInit() { 
     this.dropDownElement = document.querySelector('.header__dropdown'); 
     this.downArrowElement = this.elementRef.nativeElement; 

     this.downArrowElement.addEventListener('mouseenter',() => { this.isAbove = true; }); 
     this.downArrowElement.addEventListener('mouseleave',() => { this.isAbove = false; }); 

     this.downArrowElement.addEventListener('click',() => { 
      if (!this.isActive) { 
       this.activate(); 
      } else { 
       this.deActivate(); 
      }    
     }); 

     document.addEventListener('click',() => { 
      if (!this.isAbove) { 
       this.deActivate(); 
      }    
     }); 
    } 

    ngOnDestroy() { 
     // TODO: removeEventListener 
    } 

    private activate() { 
     this.isActive = true; 
     this.downArrowElement.classList.add('header__item--active'); 
     this.dropDownElement.classList.add('header__dropdown--active'); 
    } 

    private deActivate() { 
     this.isActive = false; 
     this.downArrowElement.classList.remove('header__item--active'); 
     this.dropDownElement.classList.remove('header__dropdown--active'); 
    } 

} 

我不明白問題。我也試圖讓這些功能不是私有的,但它仍然不起作用,並且我得到了同樣的錯誤。

回答

2

變化

this.downArrowElement.addEventListener('mouseenter', this.downArrowOnMouseEnter); 
this.downArrowElement.addEventListener('mouseleave', this.downArrowOnMouseLeave); 
this.downArrowElement.addEventListener('click', this.downArrowOnClick); 
document.addEventListener('click', this.documentOnClick); 

this.downArrowElement.addEventListener('mouseenter', this.downArrowOnMouseEnter.bind(this)); 
this.downArrowElement.addEventListener('mouseleave', this.downArrowOnMouseLeave).bind(this); 
this.downArrowElement.addEventListener('click', this.downArrowOnClick.bind(this)); 
document.addEventListener('click', this.documentOnClick.bind(this)); 

this不是指的下這些功能的指令。

+1

謝謝!現在我明白了爲什麼。它使用這個函數而不是類。 – Alex

相關問題