Dynamically add event listener

前端 未结 4 856
小鲜肉
小鲜肉 2020-11-22 10:21

I am just starting to mess around with Angular 2 and I wonder if anyone can tell me the best way to dynamically add and remove event listeners from elements.

I have

4条回答
  •  礼貌的吻别
    2020-11-22 11:01

    Renderer has been deprecated in Angular 4.0.0-rc.1, read the update below

    The angular2 way is to use listen or listenGlobal from Renderer

    For example, if you want to add a click event to a Component, you have to use Renderer and ElementRef (this gives you as well the option to use ViewChild, or anything that retrieves the nativeElement)

    constructor(elementRef: ElementRef, renderer: Renderer) {
    
        // Listen to click events in the component
        renderer.listen(elementRef.nativeElement, 'click', (event) => {
          // Do something with 'event'
        })
    );
    

    You can use listenGlobal that will give you access to document, body, etc.

    renderer.listenGlobal('document', 'click', (event) => {
      // Do something with 'event'
    });
    

    Note that since beta.2 both listen and listenGlobal return a function to remove the listener (see breaking changes section from changelog for beta.2). This is to avoid memory leaks in big applications (see #6686).

    So to remove the listener we added dynamically we must assign listen or listenGlobal to a variable that will hold the function returned, and then we execute it.

    // listenFunc will hold the function returned by "renderer.listen"
    listenFunc: Function;
    
    // globalListenFunc will hold the function returned by "renderer.listenGlobal"
    globalListenFunc: Function;
    
    constructor(elementRef: ElementRef, renderer: Renderer) {
        
        // We cache the function "listen" returns
        this.listenFunc = renderer.listen(elementRef.nativeElement, 'click', (event) => {
            // Do something with 'event'
        });
    
        // We cache the function "listenGlobal" returns
        this.globalListenFunc = renderer.listenGlobal('document', 'click', (event) => {
            // Do something with 'event'
        });
    }
    
    ngOnDestroy() {
        // We execute both functions to remove the respectives listeners
    
        // Removes "listen" listener
        this.listenFunc();
        
        // Removs "listenGlobal" listener
        this.globalListenFunc();
    }
    

    Here's a plnkr with an example working. The example contains the usage of listen and listenGlobal.

    Using RendererV2 with Angular 4.0.0-rc.1+ (Renderer2 since 4.0.0-rc.3)

    • 25/02/2017: Renderer has been deprecated, now we should use RendererV2 (see line below). See the commit.

    • 10/03/2017: RendererV2 was renamed to Renderer2. See the breaking changes.

    RendererV2 has no more listenGlobal function for global events (document, body, window). It only has a listen function which achieves both functionalities.

    For reference, I'm copy & pasting the source code of the DOM Renderer implementation since it may change (yes, it's angular!).

    listen(target: 'window'|'document'|'body'|any, event: string, callback: (event: any) => boolean):
          () => void {
        if (typeof target === 'string') {
          return <() => void>this.eventManager.addGlobalEventListener(
              target, event, decoratePreventDefault(callback));
        }
        return <() => void>this.eventManager.addEventListener(
                   target, event, decoratePreventDefault(callback)) as() => void;
      }
    

    As you can see, now it verifies if we're passing a string (document, body or window), in which case it will use an internal addGlobalEventListener function. In any other case, when we pass an element (nativeElement) it will use a simple addEventListener

    To remove the listener it's the same as it was with Renderer in angular 2.x. listen returns a function, then call that function.

    Example

    // Add listeners
    let global = this.renderer.listen('document', 'click', (evt) => {
      console.log('Clicking the document', evt);
    })
    
    let simple = this.renderer.listen(this.myButton.nativeElement, 'click', (evt) => {
      console.log('Clicking the button', evt);
    });
    
    // Remove listeners
    global();
    simple();
    

    plnkr with Angular 4.0.0-rc.1 using RendererV2

    plnkr with Angular 4.0.0-rc.3 using Renderer2

提交回复
热议问题