停止鼠标事件传播

Posted

技术标签:

【中文标题】停止鼠标事件传播【英文标题】:Stop mouse event propagation 【发布时间】:2016-05-18 08:59:11 【问题描述】:

在 Angular 中阻止鼠标事件传播的最简单方法是什么?

我应该传递特殊的$event 对象并自己调用stopPropagation() 还是有其他方法。

例如在 Meteor 中,我可以简单地从事件处理程序返回 false

【问题讨论】:

【参考方案1】:

对事件调用 stopPropagation 可防止传播:

(event)="doSomething($event); $event.stopPropagation()"

对于preventDefault,只需返回false

(event)="doSomething($event); false"

事件绑定允许执行多个语句和表达式以按顺序执行(由; 分隔,如*.ts 文件中。 最后一个表达式的结果将导致preventDefault 被调用,如果它是假的。所以要小心表达式返回的内容(即使只有一个)

【讨论】:

我自己没有尝试过,但github.com/angular/angular/issues/4782 和github.com/angular/angular/pull/5892/files 表示它应该可以工作。不过,他们最后没有;。我会改变的。 他们谈论的是防止默认操作,而不是通过父元素步进事件什么是 stopPropagation。 返回false 这非常有效。我需要在下拉列表旁边显示一个工具提示,展开后会阻止工具提示:<span #mytooltip="matTooltip" matTooltip="Number of days before levelling up" matTooltipPosition="after" (click)="mytooltip.show($event); $event.stopPropagation()"></span> 使用strict 模板检查,您需要执行(selectionChange)="selectionChange($event); $any($event).stopPropagation()" 之类的操作,或将其移至您的处理程序。【参考方案2】:

如果您在绑定到事件的方法中,只需返回 false:

@Component(
  (...)
  template: `
    <a href="/test.html" (click)="doSomething()">Test</a>
  `
)
export class MyComp 
  doSomething() 
    (...)
    return false;
  

【讨论】:

确实适用于点击事件。至少在最新版本的 Angular2 中。 返回false 调用preventDefault 而不是stopPropagation 调用 return false 确实会停止 DOM 中的传播。检查你的事实@GünterZöchbauer 它在 ng-book 中提到。 @moeabdol 一个链接至少可以证明您声称的内容,但实际上调用了preventDefault。 github.com/angular/angular/blob/…, github.com/angular/angular/blob/… 正确! @GünterZöchbauer 感谢您澄清这一点。我希望我可以分享一个链接。我按照 Nate Murray 在他的书“ng-book The Complete Book on Angular 4”中的建议返回 false;在函数结束时停止 DOM 中的事件传播。他完全按照你提到的方式描述了它。很抱歉造成误解。【参考方案3】:

最简单的方法是在事件处理程序上调用停止传播。 $event 在 Angular 2 中的工作方式相同,并且包含正在进行的事件(通过它是鼠标单击、鼠标事件等):

(click)="onEvent($event)"

在事件处理程序上,我们可以在那里停止传播:

onEvent(event) 
   event.stopPropagation();

【讨论】:

在我的自定义指令中,它不起作用。 &lt;button confirmMessage="are you sure?" (click)="delete()"&gt;Delete&lt;/button&gt;,在我的指令中:(click)="confirmAction($event),然后是confirmAction(event) event.stopPropagation(); 也尝试返回 false 似乎在处理函数stopPropogation() 中处理event 时不可用。我必须在标记中正确执行:`(click)="foo(); $event.stopPropogation()" 这不起作用,至少在放置在锚元素中时不起作用。答案是错误的。 @inorganik tnx,从模板中调用它对我有用。【参考方案4】:

我必须 stopPropagationpreventDefault 以防止按钮展开它位于上方的手风琴项。

所以...

@Component(
  template: `
    <button (click)="doSomething($event); false">Test</button>
  `
)
export class MyComponent 
  doSomething(e) 
    e.stopPropagation();
    // do other stuff...
  

【讨论】:

【参考方案5】:

如果您希望能够将其添加到任何元素而不必一遍又一遍地复制/粘贴相同的代码,您可以创建一个指令来执行此操作。就这么简单:

import Directive, HostListener from "@angular/core";
    
@Directive(
    selector: "[click-stop-propagation]"
)
export class ClickStopPropagation

    @HostListener("click", ["$event"])
    public onClick(event: any): void
    
        event.stopPropagation();
    

然后将其添加到您想要的元素中:

<div click-stop-propagation>Stop Propagation</div>

【讨论】:

它对我不起作用。点击事件没有停止:( 对我不起作用,如果我有另一个点击... 跨度> 您可能需要监听不同的鼠标事件(即mousedown、mouseup)。 @yohosuff 提出了一个很好的观点。将此方法添加到指令中:@HostListener("mousedown", ["$event"]) public onMousedown(event: any): void event.stopPropagation(); 如果这不适合你,试试这个:event.preventDefault();【参考方案6】:

使用 javascript 禁用 href 链接

<a href="#" onclick="return yes_js_login();">link</a>

yes_js_login = function() 
     // Your code here
     return false;

它应该如何在带有 Angular 的 TypeScript 中工作(我的版本:4.1.2)

模板
<a class="list-group-item list-group-item-action" (click)="employeesService.selectEmployeeFromList($event); false" [routerLinkActive]="['active']" [routerLink]="['/employees', 1]">
    RouterLink
</a>
打字稿
public selectEmployeeFromList(e) 

    e.stopPropagation();
    e.preventDefault();

    console.log("This onClick method should prevent routerLink from executing.");

    return false;

但它并没有禁用routerLink的执行!

【讨论】:

【参考方案7】:

补充来自@androidUniversity 的答案。在一行中你可以这样写:

<component (click)="$event.stopPropagation()"></component>

【讨论】:

它不应该因版本而异,因为他们试图保持 html 模板标准:) 与 angular 5 完美搭配。 正是我想要的【参考方案8】:

在 IE (Internet Explorer) 上没有任何效果。我的测试人员能够通过单击其后面按钮上的弹出窗口来破坏我的模式。因此,我听取了对我的模态屏幕 div 的点击并强制重新聚焦在弹出按钮上。

<div class="modal-backscreen" (click)="modalOutsideClick($event)">
</div>


modalOutsideClick(event: any) 
   event.preventDefault()
   // handle IE click-through modal bug
   event.stopPropagation()
   setTimeout(() => 
      this.renderer.invokeElementMethod(this.myModal.nativeElement, 'focus')
   , 100)
 

【讨论】:

【参考方案9】:

在函数后添加 false 将停止事件传播

<a (click)="foo(); false">click with stop propagation</a>

【讨论】:

【参考方案10】:

我刚刚签入了一个 Angular 6 应用程序,event.stopPropagation() 在事件处理程序上工作,甚至没有传递 $event

(click)="doSomething()"  // does not require to pass $event


doSomething()
   // write any code here

   event.stopPropagation();

【讨论】:

这是因为您正在访问window.event。从技术上讲,这已被弃用 developer.mozilla.org/en-US/docs/Web/API/Window/event。它应该可以工作,但将来可能会绊倒你。【参考方案11】:

这解决了我的问题,防止事件被孩子触发:

doSmth()
  // what ever
        <div (click)="doSmth()">
            <div (click)="$event.stopPropagation()">
                <my-component></my-component>
            </div>
        </div>

【讨论】:

【参考方案12】:

试试这个指令

@Directive(
    selector: '[stopPropagation]'
)
export class StopPropagationDirective implements OnInit, OnDestroy 
    @Input()
    private stopPropagation: string | string[];

    get element(): HTMLElement 
        return this.elementRef.nativeElement;
    

    get events(): string[] 
        if (typeof this.stopPropagation === 'string') 
            return [this.stopPropagation];
        
        return this.stopPropagation;
    

    constructor(
        private elementRef: ElementRef
    )  

    onEvent = (event: Event) => 
        event.stopPropagation();
    

    ngOnInit() 
        for (const event of this.events) 
            this.element.addEventListener(event, this.onEvent);
        
    

    ngOnDestroy() 
        for (const event of this.events) 
            this.element.removeEventListener(event, this.onEvent);
        
    

用法

<input 
    type="text" 
    stopPropagation="input" />

<input 
    type="text" 
    [stopPropagation]="['input', 'click']" />

【讨论】:

【参考方案13】:

这对我有用:

mycomponent.component.ts:

action(event): void 
  event.stopPropagation();

mycomponent.component.html:

<button mat-icon-button (click)="action($event);false">Click me !<button/>

【讨论】:

这个解决方案在角度 5 中对我有用。谢谢。 仍然有效,绝对是最简单的解决方案。谢谢先生。 工作解决方案就在那里 :) 谢谢!【参考方案14】:

我用过

<... (click)="..;..; ..someOtherFunctions(mybesomevalue); $event.stopPropagation();" ...>...

简而言之,只需用 ';' 分隔其他事物/函数调用并添加 $event.stopPropagation()

【讨论】:

【参考方案15】:

提供的大部分解决方案都是针对 Angular 11 以上的版本,对于 Angular 11 或以下的版本,我找到了可以使用的解决方法:

export class UiButtonComponent implements OnInit, OnDestroy 

  @Input() disabled = false;

  clickEmitter: Subject<any> = new Subject();

  constructor(private elementRef: ElementRef)  

  ngOnInit(): void 
    this.elementRef.nativeElement.eventListeners()
      .map(listener => this.clickEmitter.pipe(filter(event => Boolean(event))).subscribe(event => listener(event)));
    this.elementRef.nativeElement.removeAllListeners();
    this.elementRef.nativeElement.addEventListener('click', (event) => 
      if (!this.disabled) 
        this.clickEmitter.next(event);
      
    );
  

  ngOnDestroy(): void 
    this.clickEmitter.complete();
  

我基本上将每个侦听器带到当前组件并将其放在 Observable 上,然后,我只注册一个侦听器并在那里管理操作。

上面的示例是在给定布尔变量的情况下禁用按钮上的单击事件的示例。

【讨论】:

看起来你正在解决不同的问题。有许多适用于 Angular2+ 的答案。你也触摸 nativeElement。你应该避免在任何角度版本中这样做。

以上是关于停止鼠标事件传播的主要内容,如果未能解决你的问题,请参考以下文章

从可点击的谷歌地图覆盖传播鼠标事件

QML MouseArea:如何将鼠标事件传播到其他鼠标区域?

带有自定义项目的 QListView => 鼠标事件被传播

将 JavaScript 鼠标事件从一个元素传播到另一个元素?

强制 QWidget 结束事件传播

向父母发出传播模拟鼠标事件(拖动目的)的问题