我要做什么:
stackblitz链接-> stackblitz example
组件层次结构就是这样
在“ resize.directive”中。
event.stopPropagation()
和event.preventDefault()
防止事件冒泡child.component
父组件
@HostListener('click', ['$event'])
当您将鼠标悬停在内部子组件上时,可以单击以拖动并调整元素边框的大小。我正在努力的是父组件中“ click”处理程序的事件传播。
我的问题是,我不希望从父组件中触发@HostListener
click事件。即,如果您拖动子组件的边框。在鼠标悬停时,将触发ParentComponent
的click事件。
我的理解是
stopPropagation()
但是父组件仍在拾取点击事件。
使用return false
周围有很多评论。但是,基于其他问题,这似乎并不是原因,如此处指示。
话虽如此,即使我将return false
添加到指令中,事件仍然冒泡。
任何对我可能缺少的见解的赞赏。
答案 0 :(得分:0)
为澄清起见,事件监听器将从事件发生的元素开始按以下顺序触发
directive -> child -> parent -> document
据我所知,您遇到的问题归结为多种因素:
拖动边框时,鼠标最终将位于子元素之外,因此最终将触发parent.mouseup -> document.mouseup
。要捕获指令中的事件,您必须收听document.mouseup
。
您的指令正在监听document.mouseup
。 parent.mouseup
在document.mouseup
之前被触发,因此您无法在指令中停止传播。
让我们看看将边框向下拖动会发生什么:
您在边框上按。这将触发directive.mousedown -> child.mousedown -> ...
。您停止在指令中进行传播,所以一切都很好。
将鼠标拖动到底部,光标现在位于子元素的外部。
您释放鼠标。请注意,我们不再位于child元素中,因此将触发parent.mouseup -> document.mouseup
。父处理程序将在文档处理程序之前运行,因此您无法停止它。
由于down
和up
发生在父控制器中,因此现在触发了单击。同样,我们不在子元素之内,因此触发器为parent.click -> document.click
。您无法真正阻止这种情况的发生,因为父级是FIRST处理程序。
我可能会提出以下解决方案,尽管它似乎有些怪异:
HostListener('click')
触发父级点击:我们将监听parent.mousedown
和parent.mouseup
。如果它们连续快速发生,则假定是单击,因此我们“选择”了父级。// parent.component.ts
export class ParentComponent {
parentClicked: boolean = false;
down?: number;
manualClick(): void {
this.parentClicked = true;
console.log(`parent manual click`);
}
@HostListener('mousedown', ['$event'])
onMouseDown( event: MouseEvent): void {
console.log('parent down', event.target);
this.down = Date.now();
}
@HostListener('mouseup', ['$event'])
onMouseUp( event: MouseEvent): void {
console.log('parent up');
// Assume that if it's released within 100 ms, it's a click.
if (this.down && Date.now() - this.down < 100) {
this.manualClick();
this.down = undefined;
}
}
}
由于我们不听点击事件,所以现在很好:
parent.mousedown
从未发生。parent.mouseup -> document.mouseup
。由于parent.mousedown
未被触发,down = undefined
,因此我们的“点击逻辑”不会将其计为一次点击。document.mouseup
,您最终在指令中对其进行处理。现在,这里存在一个小的潜在问题:当您单击子元素时,您将触发父级的点击逻辑,因为
child.mousedown-> parent.mousedown
后跟child.mouseup -> parent.mouseup
。如果您不希望发生这种情况,可以停止在子级中传播mousedown
事件:
// child.component.ts
@HostListener('mousedown', ['$event'])
onMouseDown( event: MouseEvent): void {
console.log('child down');
event.stopPropagation();
event.preventDefault();
}