【问题标题】:passing parameters to angular directive将参数传递给角度指令
【发布时间】:2019-05-05 02:00:44
【问题描述】:

每次事件发生时,我都会让小猫了解全局 Angular 变化检测的数量,我发现 Angular 2 runOutsideAngular still change the UI 我采用了“OutSideEventHandlerDirective”策略。

但是,现在我有一个文件,其中包含 6 个指令,每个指令用于不同的事件类型。

我想做的是将事件类型传递给指令;即设置 @Input() 事件:字符串 = '我的事件类型' 在模板 html 的指令内。

这可能吗?

所以,谢谢你到目前为止的回答。 添加为编辑以提供比评论更好的演示:

要学习的东西:

1/ @input () xyz: string = 'hello' - 您可以使用 (outSideEventHandler)="onEv($event)" [xyz]="goodbye"

在模板中设置此输入

2/ @input ('abc') xyz: string = 'hello' - “重命名”你用来引用输入的东西,即现在你使用 [abc]="goodbye"

问题补充:

3/ 我在同一个元素上使用了两个或多个“外部”指令。 如果你有 (outSideEventHandler)="onEvent1($event)" [event]="mousedown" (outSideEventHandler)="onEvent2($event)" [event]="mouseup" - 那么你会得到两个指令副本,但是两者都使用 event=mousedown。

我可以创建指令的两个(或更多)副本(请参阅code),然后为每个具有单独的唯一命名输入。但这是唯一的方法吗?

  (outSideEventHandler1)="onTestDirective($event)" 
  [outSideEvent1]="'mousedown'" 
  (outSideEventHandler2)="onTestDirective($event)" 
  [outSideEvent2]="'mouseup'" 

【问题讨论】:

    标签: angular angular6 angular-directive


    【解决方案1】:

    您可以通过使用带有 @Input 装饰器的别名来添加其他参数。

    这是一个示例,您可以如何使用另一个参数从链接的帖子中扩展指令。

    import { NgZone, ElementRef, EventEmitter, Input, Output, Directive } from '@angular/core'
    
    @Directive({
      selector: '[outSideEventHandler]'
    })
    export class OutSideEventHandlerDirective {
      private handler: Function;
    
      @Input() event: string = 'click'; // pass desired event
      @Output('outSideEventHandler') emitter = new EventEmitter();
      @Input('outSideEventType') type = 'default type';
    
      constructor(private ngZone: NgZone, private elRef: ElementRef) {}
    
      ngOnInit() {
        console.log(this.type);
        this.ngZone.runOutsideAngular(() => {
          this.handler = $event => this.emitter.emit($event);
          this.elRef.nativeElement.addEventListener(this.event, this.handler);
        });
      }
    
      ngOnDestory() {
        this.elRef.nativeElement.removeEventListener(this.event, this.handler);
      }
    }
    

    你可以这样使用它:

    <button (outSideEventHandler)="onTestDirective()" [outSideEventType]="'My type'">Test Directive</button>
    

    这里还有一个link 指向实现它的 StackBlitz 示例。它将类型输出到控制台日志中,以便您可以确定它是否已应用。

    这也是多事件处理程序注册的解决方案,也可以回答您的添加。 为此,我认为最好的解决方案是仅使用默认输入参数并将一组事件名称和处理程序对发送到指令。例如,您可以创建一个对象 EventHandler:

    export class EventHandler {
      public event: string;
      public handler: EventListener;
    }
    

    然后将指令更改为仅接受一个默认输入,即 EventHandler 对象数组。

    import { NgZone, ElementRef, EventEmitter, Input, Output, Directive } from '@angular/core';
    import { EventHandler } from './event-handler';
    
    @Directive({
      selector: '[outSideEventHandlers]'
    })
    export class OutSideEventHandlerDirective {
      @Input() public outSideEventHandlers: EventHandler[];
    
    
      constructor(private ngZone: NgZone, private elRef: ElementRef) {}
    
      ngOnInit() {
        this.ngZone.runOutsideAngular(() => {
          for (let eventHandler of this.outSideEventHandlers) {
            console.log(eventHandler.event);
            this.elRef.nativeElement.addEventListener(eventHandler.event, eventHandler.handler);
          }
    
        });
      }
    
      ngOnDestory() {
        for (let eventHandler of this.outSideEventHandlers) {
            this.elRef.nativeElement.removeEventListener(eventHandler.event, eventHandler.handler);
          }
      }
    }
    

    那你在模板中这样使用:

    <button [outSideEventHandlers]="[{ event: 'click', handler: onClick }, { event: 'mousedown', handler: onMouseDown }, { event: 'mouseup', handler: onMouseUp}]">Test Directive</button>
    

    这样,您可以在同一元素上添加任意数量的处理程序,而无需在指令上添加任何其他属性。这是实现此方法的 StackBlitz 示例的link

    【讨论】:

    • 感谢您提供完整的示例;我已经请开发人员仔细查看,看看这是否适合我们的场景;会传回去让大家知道:)
    • ok,玩过代码,看问题的修改;快到了:)
    • 我已经用不同的解决方案扩展了答案,以解决您的问题。
    • 创新方法。这对我来说效果很好..... 注意:1/您只能在一个元素上拥有一次指令实例,因此将数组传递给指令是一个很好的解决方案。 2/奇怪的是,当使用 Angular EventEmitter 发送事件时,您可以记录事件并查看所有内部结构,但是使用此解决方案我们看到的是原始浏览器事件,其中 console.log 没有列出事件的内容;但是,记录 ev.altKey 可以工作并证明它们在那里 - 所以我们实际上可能比 Angular 版本有性能提升。再次感谢 AlesD :)
    • 我的最终版本:link - 只是增加了使用对象或对象数组的能力。
    【解决方案2】:
    Directive({
        selector: '[testDirective]'
    })
    export class TestDirective implements OnInit {
    
        @Input() testDirective: string;
    
        @Input() otherInput: string = 'Saving'; // if you need more than one input
    }
    

    模板

    <button [testDirective]="<event-name>" // this will add the directive and also set the input
            [otherInput]="<other-input>"> // other input
    </button>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-13
      • 2020-02-06
      • 2015-06-28
      • 1970-01-01
      • 1970-01-01
      • 2015-06-10
      相关资源
      最近更新 更多