Angular 5 带参数的组件输入函数

Posted

技术标签:

【中文标题】Angular 5 带参数的组件输入函数【英文标题】:Angular 5 Component input function that takes parameters 【发布时间】:2018-06-09 07:23:04 【问题描述】:

在 Angular 2+ 组件中,如何传入带参数的回调函数? 我最初的假设是这样的

<app-example [onComplete]="doThing('someParam')"></app-example>

有时我不需要任何参数,像这样:

<app-example [onComplete]="doSomeThingElse()"></app-example>

然后在我拥有的组件中

import  Component, OnInit  from '@angular/core';

@Component(
  selector: 'app-example',
  templateUrl: './example.component.html',
)
export class ExampleComponent 
  @Input() public onComplete: () => void;

  //run `this.onComplete()` somewhere as needed

但是,最终发生的事情是 doThing('someParam')doSomeThingElse() 在没有任何交互的情况下立即被调用。

我应该如何将回调函数传递给稍后调用的组件?


编辑:

我在这里试图解决的实际问题是能够在以后运行任何传入的函数。这是一个确认组件,它将询问用户“您确定要继续吗?”然后如果他们按下“是的,我确定”按钮,传入的函数就会运行。

【问题讨论】:

@yurzui 这不是用事件重新发明***,并且有内存泄漏的潜在危险吗? (不是你的解决方案,而是意图本身) @deezg bind 方法将在每次角度调用更改检测周期时返回新函数。所以我同意我们不应该重新发明***) 你应该阅读@Output。这就是你要找的。​​span> @toskv 我知道@Output 将值传递回父控制器,但我不确定在这种情况下如何使用它。随意添加详细信息对此问题的答案,我会将其标记为正确。现在告诉我“阅读”某些东西对我没有多大帮助。 @ChrisBarr 您最好实际描述您要解决的问题。问题不是“将回调函数作为变量传递”,而是您希望组件解决的真正问题。通常的解决方案是将参数作为@Input 参数发送给孩子,然后将事件与@Output 绑定,并且将使用您想要的任何参数引发事件。当事件被引发时,你的父组件将使用它通过事件获得的任何参数调用它想要的任何函数(在上面的情况下是你的回调)。 【参考方案1】:

您可以在组件中使用私有方法:

private doThingFactory(param) 
  return () => this.doThing(param);

然后像这样使用它:

<app-example [onComplete]="doThingFactory('someParam')"></app-example>

【讨论】:

我认为这可能有效,但如果可能的话,我想避免这种情况。看来 Angular 应该只是有一种方法来传递一个函数并在以后调用它 实际上,这不是最佳实践。 Angular 鼓励你使用 Input 和 Output 来解决你的问题,如果可能的话不要使用回调函数。您应该发送 someParam 作为输入并接收结果作为输出。 我认为@Output 是他正在寻找的。也许也添加一个例子? 我认为最好使用公共方法。因为该方法将涉及到课外的html。有时检查可能会导致编译错误,尽管 javascript actaully 中没有公共/私有方法。【参考方案2】:

这是@toskv 正在寻找的@Output 语法示例Angular pass callback function to child component as @Input

所以对于你的例子,

<app-example 
  (onComplete)="doThing()" 
  [completedParam]="'someParam'"></app-example>
@Component(
  selector: 'app-example',
  templateUrl: './example.component.html',
)
export class ExampleComponent 
  @Output() public onComplete: EventEmitter<any> = new EventEmitter();
  @Input() completedParam;

  runOnComplete(): void 
    this.onComplete.emit(this.completedParam);
  

感觉不如[onComplete]="doThing.bind(this, 'someParam')"

【讨论】:

我能够删除 @Input() completedParam; 并调用 this.onComplete.emit(),它适用于我传入或未传入的任何内容。谢谢! 有趣,所以(onComplete)="doThing('someParam')"?我想这没关系,因为 param 在编译时是一个固定的字符串? 是的,这行得通,我很高兴,因为如果父控制器具有我需要运行的功能,但随后必须无参数传递它并在某些参数上传递参数,这会让人感到困惑其他绑定。这正是我希望的工作!实际上我最初确实尝试过这个,但是我遇到了另一个问题并认为它是相关的,所以我回溯并发布了这个问题。哦,好吧!【参考方案3】:

模板:

<app-example [someParams]="someParamsObject"
             (complete)="onComplete($event)" >
</app-example>

组件:

@Component(
  selector: 'app-example',
  templateUrl: './example.component.html',
)
export class ExampleComponent 
  @Input()
  someParams: YourParamsType;

  @Output()
  complete:EventEmitter<any> = new EventEmitter<any>();

  //run `this.complete(this.someParams)` somewhere as needed and 
  //pack in some params if you need

在调用父组件时,您需要一个名为onComplete 的函数,在这种情况下接收any 类型的参数(来自@Output 被定义为EventEmitter&lt;any&gt;)。如果需要,您还可以拥有任何您喜欢的特定类型的事件参数EventEmitter&lt;YourParticularType&gt;

【讨论】:

【参考方案4】:

仅当您有一个需要调用而不对组件本身采取操作的方法时,上述解决方案才有效。但是,就我而言,我需要在 app-example 组件内执行一个可观察的方法,并等待响应在该组件内执行一些操作。

如果有人有同样的问题。这是它的解决方案。

    创建一个接口。

    export interface Delegate<T> 
      (...args: any[]): T;
    
    

    在您的角度组件上,创建一个@Input 变量

    @Component(
        selector: 'app-example',
        templateUrl: './example.component.html',
    )
    export class AppExampleComponent 
      @Input() executeWhen: Delegate<Observable<any>>;
    
      runOnComplete(): void 
        this.executeWhen().subscribe(() => // do some action);
      
    
    

【讨论】:

创建接口是利用@Input的解决方案,回调函数可以稍后调用,而不是设置为@Output参数。

以上是关于Angular 5 带参数的组件输入函数的主要内容,如果未能解决你的问题,请参考以下文章

在组件中调用带参数的函数

带参数的函数的调用()

两个构造函数(带 & 不带参数),无输入 -> 无参数运行。跳过上述类中的构造函数

如何自动装配在 SpringBoot 应用程序中具有带参数的构造函数的组件

带输入参数的 Oracle PL/SQL 函数

Angular:带参数的 npm 脚本