繁体   English   中英

使用 Angular EventEmitter 的正确方法

[英]Proper way to use Angular EventEmitter

在我的简化场景中,有一个parent组件,其中包含所有业务逻辑。

parent组件创建一个仅负责显示按钮列表的child组件。

我想处理parent中此类按钮的单击事件,但是,使用建议的EventEmitter模式,我不得不在parent中使用无用的switch case ,以检测按下了哪个按钮。

直接将回调作为child的输入传递会容易得多,但我认为这不是一个好习惯。 据我所知,这些回调也是在孩子的上下文中执行的,这不是预期的结果。

我错过了什么吗? 有没有更好的方法来满足我的需求? 还是我完全以错误的方式解决了这个问题?

家长:

import { Component } from "@angular/core";

@Component({
  selector: "parent",
  template: ` <child
      [buttons]="buttons"
      (click)="onButtonClick($event)"
    ></child>
    <span>{{ description }}</span>`
})
export class ParentComponent {
  description = "";
  buttons = ["foo", "bar", "baz"];

  onButtonClick(button: string) {
    switch (button) {
      case "foo":
        this.description = "Calling foo()";
        this.foo();
        break;
      case "bar":
        this.description = "Calling bar()";
        this.bar();
        break;
      case "baz":
        this.description = "Calling baz()";
        this.baz();
        break;
    }
  }

  foo() {}
  bar() {}
  baz() {}
}

孩子:

import { Component, EventEmitter, Input, Output } from "@angular/core";

@Component({
  selector: "child",
  template: ` <span *ngFor="let button of buttons">
    <button (click)="onClick(button)">{{ button }}</button>
  </span>`
})
export class ChildComponent {
  @Input() buttons: string[];

  @Output() click = new EventEmitter<string>();

  onClick(button: string) {
    this.click.emit(button);
  }
}

和一个工作沙箱

你可以发射任何东西

//父母

@Component({
  selector: "parent",
  template: ` <child
      [buttons]="buttons" (click)="$event()"
    ></child>
    <span>{{ description }}</span>`
})
export class ParentComponent {
  description = "";
  buttons = [
    { name: "foo", callback: this.foo},
    { name: "bar", callback: this.bar},
    { name: "baz", callback: this.baz},
  ];
  foo(){}
  bar(){}
  baz(){}
}

//孩子

@Component({
  selector: "child",
  template: ` <span *ngFor="let button of buttons">
    <button (click)="onClick(button)">{{ button.name }}</button>
  </span>`
})
export class ChildComponent {
  @Input() buttons: any[];

  @Output() click = new EventEmitter<any>();

  onClick(button: any) {
    this.click.emit(button.callback);
  }
}

Update Sound "bizarro" 传递一个函数并使用 function() 执行,但我们需要认为函数只是一个对象。

想象一下你定义了两个函数

function1(){console.log("I'm function 1")}
function2(){console.log("I'm function 1")}

在事件点击中,我们调用一个函数

click()
{
   const mainFunction=this.function1
   mainFunction() //execute the function1
}

或根据变量

click()
{
   const mainFunction=this.condicion?this.function1:this.function2
   mainFunction() //execute the function1 or the function2 
                  //if condition is true or false
}

变量、对象、数组、函数...物理存储在内存位置。 变量、对象、函数的“名称”……只是指向该内存的“指针”。

如果我们愿意,我们可以在答案中写

    <child [buttons]="buttons" (click)="executeFunction($event)"></child>

   executeFunction(mainFunction:any)
   {
         mainFunction()
   }

如果我们想要,如果我们的所有函数都没有参数并且没有返回任何内容,我们可以键入函数以提供更清晰的信息,而不是使用这个丑陋的“任何”用法

   executeFunction(mainFunction:()=>void)
   {
         mainFunction()
   }

@Output() click = new EventEmitter<()=>void>();

您可以考虑在对象数组而不是字符串数组中提供回调。

编辑沙盒: https ://codesandbox.io/s/cocky-brahmagupta-ueg4nv

父母

import { Component } from "@angular/core";

@Component({
  selector: "parent",
  template: ` <child
      [buttons]="buttons"
    ></child>
    <span>{{ description }}</span>`
})
export class ParentComponent {
  description = "";
  buttons = [
    { name: "foo", callback: () => { this.description = "Calling foo()" } },
    // bar
    // baz
  ];
}

孩子

@Component({
  selector: "child",
  template: ` <span *ngFor="let button of buttons">
    <button (click)="button.callback()">{{ button.name }}</button>
  </span>`
})
export class ChildComponent {
  @Input() buttons: MyButton[];
}

界面

interface MyButton {
  name: string,
  callback: () => void;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM