Angular 2 - 绑定和解绑 HostListener 事件

3

我正在尝试根据组件的输入变量绑定和解绑HostListener click事件。

该组件是一个弹出窗口,只有一个名为show的输入变量。该输入变量保存着弹出窗口的激活/非激活状态。我想在整个文档上触发click事件,但只限于输入变量show设置为true时。

是否有一种方法可以在我现有的ngOnChanges函数内绑定和解绑hostlistener事件?

我目前的代码如下:

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
        }
    }
}

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

你想解除事件绑定而不是设置一个标志来确定是否跳过处理程序的其余部分,有什么原因吗?无论哪种方式,性能差异可能都不大(据我所知)。 - GregL
我已经尝试过这种方法,但不幸的是,它引发了一个问题。当我通过单击事件在单独的按钮上切换弹出窗口“show”时,HostListener单击事件会触发。该事件在“show”输入更改后而不是之前触发。 - Carlton
你尝试过使用一个单独的标志来进行show吗?在ngOnChanges()处理程序中设置和清除该标志,希望这意味着您想要发生的事情顺序将被执行。 - GregL
很不幸,这种方法会导致性能大幅下降。例如,一个页面有20多个带有HostListener事件的弹出组件。 - Carlton
2个回答

2
为确保在弹出窗口显示时,只设置一个主机监听器,请引入一个名为PopupBody的新子组件,在其上添加主机监听器并使用@Output()将事件传递回Popup组件。
然后,在模板中,使用*ngIf="show"PopupBody组件进行条件判断,这样它只会在弹出窗口显示时绑定主机监听器,并且在弹出窗口隐藏时取消绑定。

-1
最终我使用了一个服务来实现解决方案。该服务处理文档上的点击事件,并使用可观察对象使组件能够订阅该事件。
当弹出窗口组件打开时,它会订阅stateService的点击可观察对象,并在关闭时取消订阅。
弹出窗口组件:
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的方法,请分享 :) - Carlton

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接