【问题标题】:Angular 2 - Binding and Unbinding HostListener EventsAngular 2 - 绑定和解除绑定 HostListener 事件
【发布时间】:2017-01-10 00:45:05
【问题描述】:

我正在尝试根据组件的输入变量绑定和取消绑定 HostListener 点击事件。

该组件是一个弹出窗口,它有一个名为show 的输入。此输入保存弹出窗口的活动/非活动状态。我想在整个文档上触发点击事件,但前提是输入 show 设置为 true。

有没有办法在我拥有的 ngOnChanges 函数中绑定和取消绑定主机侦听器事件?

我拥有的当前代码:

import {Component, OnInit, Input, ViewEncapsulation, HostListener} from '@angular/core';

@Component({
    selector: 'custom-popup',
    templateUrl: './popup.component.html',
    styleUrls: ['./popup.component.scss'],
    encapsulation: ViewEncapsulation.None
})
export class PopupComponent implements OnInit {

    @Input() show: boolean = false;

    constructor() {
    }

    ngOnInit() {
    }


    @HostListener('document:click', ['$event.target'])
    clickHandler(targetElement) {
        // Custom code to handle click event
    }

    ngOnChanges(show: boolean) {
        if (this.show) {
            // Bind Click Event
        }
        else {
            // Unbind Click Event
        }
    }
}

我们将不胜感激任何帮助和见解。

【问题讨论】:

  • 您是否有理由要取消绑定事件,而不仅仅是设置一个标志来确定是否跳过处理程序的其余部分?无论哪种方式,性能差异都可能不会太大(AFAIK)。
  • 我已经尝试过这种方法,但不幸的是这引发了一个问题。当我使用单独按钮上的单击事件切换弹出窗口show 时,HostListener 单击事件会触发。该事件在 show 输入未更改后触发。
  • 您是否尝试过对show 使用单独的标志?在ngOnChanges() 处理程序中设置并清除该标志,希望这意味着您希望事情发生的顺序将被强制执行。
  • 不幸的是,这种方法的性能下降很大。即一个页面有 20 多个带有主机监听事件的弹出组件。

标签: javascript angular dom-events


【解决方案1】:

为确保在显示弹出窗口时仅设置 1 个主机侦听器,请引入一个新的子组件 PopupBody,其中包含主机侦听器,以及一个 @Output() 将事件传递回 @987654323 @组件。

然后,在您的模板中,使用*ngIf="show" 使PopupBody 组件成为条件组件,然后它应该只在弹出窗口显示时绑定主机侦听器,并在弹出窗口隐藏时取消绑定。

【讨论】:

    【解决方案2】:

    最后,我使用服务实现了一个解决方案。该服务处理文档上的点击事件,并使用 observable 使组件能够订阅该事件。

    弹窗组件在打开时订阅stateService点击observable,在关闭时取消订阅。

    弹出组件:

    import {Component, OnInit, Input, ViewEncapsulation, HostListener} from '@angular/core';
    import {StateService} from "../services/state.service";
    import {Subscription} from "rxjs";  
    
    @Component({
        selector: 'custom-popup',
        templateUrl: './popup.component.html',
        styleUrls: ['./popup.component.scss'],
        encapsulation: ViewEncapsulation.None
    })
    export class PopupComponent implements OnInit {
    
        @Input() show: boolean = false;
    
        constructor(private stateService: StateService) {
        }
    
        ngOnInit() {
        }
    
        ngOnChanges(show: boolean) {
    
            if (this.show) {
    
                // Timeout to ensure subscription after initial click
                setTimeout(() => {
    
                    // Subscribe to the document click service when the input opens
                    if (!this.clickSubscription || this.clickSubscription.closed) {
                        this.clickSubscription = this.stateService.documentClick$.subscribe(targetElement => {
                            // Logic for closing the popup
                        });
                    }
                });
            }
            else {
    
                // Remove the subscription when the input closes
                if (this.clickSubscription && !this.clickSubscription.closed) {
                    this.clickSubscription.unsubscribe();
                }
            }
        }
    }
    

    @GregL 谢谢你的建议

    【讨论】:

    • 这种方法确实是我希望的替代方法。因此,如果有人确实遇到了绑定和解除绑定 HostListeners 的方法,请分享:)
    猜你喜欢
    • 2020-03-22
    • 1970-01-01
    • 1970-01-01
    • 2020-02-26
    • 2012-11-11
    • 2016-08-08
    • 2011-07-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多