【问题标题】:Angular2 Directive to modify click handlingAngular2指令修改点击处理
【发布时间】:2016-11-23 19:24:30
【问题描述】:

我正在尝试编写一个 Angular2 属性指令来修改某些元素的行为。更具体地说,我想将属性应用于具有点击处理程序的某些元素,并防止绑定函数在某些条件下执行。

所以现在我有一个元素,例如:

<button (click)="onClick(param1, param2)"></button>

onClick 是在承载按钮元素的组件上声明的函数。

我想做的是这样写:

<button (click)="onClick(param1, param2)" online-only></button>

并有一个类似的指令:

@Directive({
  selector: '[online-only]',
})
export class OnlineOnlyDirective {
  @HostListener('click', ['$event']) 
  onClick(e) {
    if(someCondition){
      e.preventDefault();
      e.stopPropagation();
    }
  }
}

但是单击处理程序首先执行,因此我的指令没有机会停止执行。

我想到的第二种方法是用我自己的处理程序替换(单击),例如([onlineClick]="onClick")并在指令认为合适时执行传递的函数,但是这样我不能将参数传递给 onClick 函数和看起来有点奇怪。

你对做这样的事情有什么想法吗?

【问题讨论】:

    标签: javascript angular ionic2 angular2-directives


    【解决方案1】:

    我不知道如何强制 Angular 首先执行某个事件处理程序。一种解决方法可能是使用自定义事件,例如:

    <button (myClick)="onClick(param1, param2)" online-only></button>
    
    @Directive({
      selector: '[myClick]',
    })
    export class OnlineOnlyDirective {
      @Output() myClick: EventEmitter = new EventEmitter();
      @HostListener('click', ['$event']) 
      onClick(e) {
        if(someCondition){
          e.preventDefault();
          e.stopPropagation();
        } else {
          this.myClick.next(e);
        }
      }
    }
    

    【讨论】:

    • 是的,采用我描述的第二种方法要好得多。使用 EventEmitter 而不是传入要调用的函数会有所不同。第一种方法会更优雅,但正如你所说的那样,angular2 可能不支持。
    • 只是好奇选择器是否应该是 '[online-only]' ?试图弄清楚该指令发生了什么。
    • 我不知道online-only是否或如何与问题相关
    • 我认为选择器应该是selector: '[online-only]',。它是拉入此指令的粘合剂。
    【解决方案2】:

    到目前为止,这是不可能的(仅使用(单击)绑定)。这是因为通过 Angular -> 通过(单击)绑定 @HostListner 注册的所有事件都通过单个侦听器进行代理。这就是为什么在这种情况下调用 stopPropagation 或更正确的方法 stopImmediatePropagation 不起作用的原因,因为您不再有单独的事件侦听器。更多详情请参考此问题:https://github.com/angular/angular/issues/9587

    【讨论】:

      【解决方案3】:

      我最近经历了一些我想做的类似事情,但建议的答案没有奏效,可能是因为我在自定义组件上有点击处理程序。这就是我所做的。

      <button (myClick)="onClick(param1, param2)" online-only></button>
      

      或者

      <my-cmp (myClick)="onClick(param1, param2)" online-only></my-cmp>
      

      指令可能如下所示:

      @Directive({
         selector: '[online-only]',
      })
      export class OnlineOnlyDirective implements OnInit {
         constructor(private el: ElementRef) { }
      
         ngOnInit() {
            if (someCondition) {
               this.el.nativeElement.removeAllListeners('click');
            }
         }
      }
      

      这将移除组件或元素上的点击事件监听器。这不会是反应性的,因此如果someCondition 发生变化,则必须有一种方法可以将点击侦听器放回原处。不过我不需要这个用例。

      更新

      这在开发中对我有用,但在生产环境中缩小代码时对我不起作用。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-06-30
        • 1970-01-01
        • 2017-11-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多