我有“Card”组件正在侦听外部点击或滚动事件,并在发生此事件时被销毁。
@HostListener('document:mousedown', ['$event'])
public onEvent(e: Event): void {
let el = this.elementRef.nativeElement;
if (e.target !== el && !el.contains(e.target)) {
this.destroyCard();
}
}
ngAfterViewInit() {
document.addEventListener('scroll', this.onEvent, true);
}
问题来自于此组件我创建模态窗口,该窗口在应用程序视图根目录中的此组件外部创建。当我点击模态窗口或滚动它时,我的卡片组件会随着模态窗口一起被销毁。
这是沙箱stackblitz with click。 当你点击模态窗口时,它应该保持不变。
已更新即可。修复了event.stopPropagation()。
但它不适用于通常不像滚动的泡沫这样的事件。请参阅stackblitz with scroll。
我只看到一个解决方案:创建将侦听事件的服务,我的Card组件和Modal窗口组件将订阅并将它们添加到数组中,将检查事件目标是否放置在此节点内。
也许有人知道更好的解决方案?
答案 0 :(得分:2)
您可以处理模态组件中的mousedown
事件,并调用event.stopPropagation()
以确保它未达到document
级别。您可以在this stackblitz中看到结果。
export class ModalWindowComponent {
@HostListener('mousedown', ['$event'])
public processMouseDown(event: MouseEvent): void {
event.stopPropagation();
}
}
重要:请务必致电event.stopPropagation()
,而不是event.stopImmediatePropagation()
。
event.stopPropagation()
可防止事件冒泡到元素的祖先(参见MDN documentation)event.stopImmediatePropagation()
只是阻止调用元素上的其余侦听器(参见MDN documentation)对于滚动事件,调用event.stopPropagation
不起作用。如果滚动元素具有特定属性,则可以保持模态打开,例如data-keepmodalopen="true"
(小写)。以下是此类检查的代码(有关演示,请参阅 this stackblitz ):
<div class="container">Modal window. I should stay
<div class="scroll-container" data-keepmodalopen="true">
...
</div>
</div>
public onScroll(e: MouseEvent): void {
if (this.window && !this.keepModelOpen(e.target as HTMLElement)) {
this.window.destroy();
this.window = null;
}
}
public keepModelOpen(element: HTMLElement): boolean {
return element.dataset.keepmodalopen === "true";
}