angular - 如何检查事件目标是否在一个元素内?
问题描述
我有“卡片”组件,它正在侦听外部单击或滚动事件,并在发生此事件时被销毁。
@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);
}
当我从这个组件创建模态窗口时,问题就出现了,它是在应用程序视图根目录中的这个组件之外创建的。当我单击模态窗口或在其上滚动时,我的卡片组件与模态窗口一起被销毁。
这是带有 click的沙盒堆栈闪电战。当您单击模态窗口时,它应该保留。
更新。用 event.stopPropagation() 修复。
但它不适用于通常不像滚动这样的气泡的事件。请参阅带有滚动的 stackblitz。
我只看到一个解决方案:创建将侦听事件的服务,我的 Card 组件和 Modal 窗口组件将订阅并将它们的节点添加到数组中,该数组将检查事件目标是否放置在该节点内。
也许有人知道更好的解决方案?
解决方案
您可以mousedown
在模态组件中处理事件,并调用event.stopPropagation()
以确保它没有达到document
级别。你可以在这个 stackblitz中看到结果。
export class ModalWindowComponent {
@HostListener('mousedown', ['$event'])
public processMouseDown(event: MouseEvent): void {
event.stopPropagation();
}
}
重要提示:一定要打电话event.stopPropagation()
,不要event.stopImmediatePropagation()
。
event.stopPropagation()
防止事件冒泡到元素的祖先(参见MDN 文档)event.stopImmediatePropagation()
只是防止调用元素上的其余侦听器(请参阅MDN 文档)
对于滚动事件,调用event.stopPropagation
不起作用。如果滚动元素具有特定属性,例如data-keepmodalopen="true"
(小写),您可以保持模式打开。这是这种检查的代码(参见这个 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";
}
推荐阅读
- r - 使用 SSlogis 将逻辑曲线拟合到数据:错误 NA/NaN/Inf
- php - PHP $_GET 没有获得任何价值
- html - 无法使用 html 播放压缩的 wav 文件
- java - 更改活动时 Android 应用程序崩溃
- .htaccess - .htaccess 重定向新域和新 url 结构
- python-3.x - 将 python 列表传递给 keras model.fit
- python - Azure 事件中心如何获取最新消息
- angular - 拦截器导致“当前请求不是多部分请求”500 错误
- python - Pandas:如何填充 df A 中的列,仅当 df A 中的前四列与 df B 匹配时,来自 df B 中的值
- http - 如何在 Go 中验证签名证书时间戳 (SCT)