【问题标题】:Angular 2 how to pass function with params to a child component?Angular 2如何将带有参数的函数传递给子组件?
【发布时间】:2016-08-19 17:18:11
【问题描述】:

当函数接受参数时,如何正确地将函数从父组件传递给子组件?

在 ngOnInit 中,如何定义函数的范围:

addToList(id) {
  this.store.dispatch(this.listActions.addToList(id));
}

ngOnInit,现在是错误的。

ngOnInit() {
  this.addToList = this.addToList.bind(this, id);
}

在我的父组件中,我有 addToCart(id) 函数。

我想将该函数传递给我的子组件,它有一个项目列表,并且在单击项目上的添加按钮时,我想将 addToCart(item_id) 回调到父组件。

【问题讨论】:

  • 为什么需要传递一个函数?也许使用一个事件,这似乎更有棱角
  • id应该固定还是子组件可以传一个id?
  • 传递函数不好吗?可以举个例子吗
  • 所以每个项目都有一张卡片,您可以单击添加将该 item_id 添加到列表中。所以我想用 item_id 做一个回调
  • 子组件会传递item_id

标签: javascript angular typescript


【解决方案1】:

@Maarek 的回答很好,而且可能是“正确”的做法。我在这里介绍的是一种更简单的方式,专门用于从子级与父级进行通信。

您在原始帖子中提出的建议是让 Parent 向 Child 发送回调方法,以便 Child 可以在适当的时候使用数据调用它。为了完成这个特定的任务(从 Child 到 Parent 的关于 Child 中的某些操作的数据),使用 Events 是合适的,使用 Child 内部的 EventEmitter。请参阅此 API 参考,其中有一个示例:https://angular.io/docs/ts/latest/api/core/index/EventEmitter-class.html 和我作为演示制作的这个 Plunker:https://embed.plnkr.co/T1wFqVOhMXgX6NRfTuiC/

在孩子中,你有这样的代码:

import { Component, Input, Output, EventEmitter } from '@angular/core';
@Component({
  selector: 'item',
  template: `
    <div class="item">
      <button type="button" (click)="addItem()">Add</button>
      <p>{{id}}
    </div>
  `
})
export class ItemComponent {
  @Input() id: string;
  //key line here: this emitter can be bound to by parent to get notifications
  @Output() add: EventEmitter<string> = new EventEmitter<string>();

  constructor() { }

  addItem() {
    //then when the button is clicked, emit events to the parent.
    this.add.emit(this.id);
  }
}

Parent 会像这样调用创建组件:

&lt;item id="1" (add)="addToList($event)"&gt;&lt;/item&gt; 其中addToList() 是 Parent 上的一个函数,它执行您的回调打算执行的工作。 $event 是从孩子(id)传递过来的数据。

【讨论】:

  • 在onClick中,那你也怎么抓取一些数据呢?所以(onClick)="addToList(item_id)"?我正在尝试使用 $event 但这并不能真正帮助我,对吗?我得到的数据在 {{item_id}} 或 {{item_name}} 等中。
  • on click 转到 addItem(),addItem() 是 Child (Item) 类的一个方法。所以它可以直接访问项目的任何变量/内容。就像在示例中一样,我得到了 id,但它可以是任何东西。如果您有多个要发送的内容,可以将它们捆绑到一个对象中: addItem() { let event = { "id": this.item_id, "name": this.item_name }; this.add.emit(event); } 然后在父级上: ... addTooList(event) { let id = event.id;让名称 = 事件名称; }
  • 啊。我的意思是这样的,其中我的组件根据我传递的数组渲染出项目,但每个项目都有一个按钮。单击时我只想发送那个特定的 item_id? &lt;button class="btn btn-highlight btn-sm" (click)="handleAddToList()"&gt;Add &lt;i class="fa fa-plus-circle"&gt;&lt;/i&gt;&lt;/button&gt;
  • nvm 想通了,呵呵:D
  • 问题是如何将函数从父母传递给孩子,但答案是从孩子传递给父母。所以这并不能回答问题。
【解决方案2】:

这里没有太多细节,但从我收集的信息来看,我认为您需要的是一个可注入服务(此处演示:https://angular.io/docs/ts/latest/tutorial/toh-pt4.html)来处理组件之间共享的数据对象。与其在这里输入一堆代码(最好在教程的那个页面显示),我将描述我认为你正在尝试做什么以及我将如何去做。

整个商店数据模型可以通过一个服务(store.service.ts 可能)来处理。这将使您的 CRUD 函数针对商店模型的不同属性公开。您在此处添加的列表应该有一个公共 getter,它返回服务中列表的可观察对象,以及一个用于从列表中添加和删除的公共函数。像这样的:

@Injectable
export class StoreService {
  private _storeList:BehaviorSubject<Array<any>> = new BehaviorSubject<Array<any>>([]);

  /*I'm sure the store has other properties, set them up here. I'd suggest
    breaking any arrays out of the general object (unless you want to use
    pipes which are awesome but keeping it simple here) but if the store has
    a lot of general properties (name, address, whatever) they can be stored 
    in a single BehaviorSubject of type any.
  */

  constructor(){}

  get StoreList() { return this._storeList.asObservable() }

  public addToList(id) {
      let curVal = this._storeList.getValue();
      curVal.push(id);
      this._storeList.next(curVal);
  }

}

然后,您可以将此服务注入到父子 constructor(private _storeService:StoreService){}(以及任何其他需要它的组件)的构造函数中。然后孩子可以订阅列表:get List() { return this._storeService.StoreList },父母可以调用 add 函数添加到列表中。需要注意的一点是,当您将它作为 *ngFor 添加到模板时,请确保通过异步管道传递值。 *ngFor="List | async" 或者你可能会想弄清楚为什么会出错。

这篇文章在这方面对我也有很大帮助(尽管我可能建议一开始避免使用不可变,直到您完全熟悉 Angular 2):http://blog.angular-university.io/how-to-build-angular2-apps-using-rxjs-observable-data-services-pitfalls-to-avoid/

【讨论】:

  • 阅读上面的 cmets(我写这篇文章时不在那里)现在看起来我没有看到你想要做什么。我还是要把它留在这里,因为它可能对你有用。
  • 谢谢。这是一个很大的帮助。但是,让我更新我的问题以解释更多细节!
  • 在过去的几周里,我确实遇到过同样的问题,但我不记得我最终做了什么。我会留意细节,看看是否可以在我的代码库中找到它。
  • 我不太喜欢像这样的东西发出,因为将逻辑保留在父级中感觉“更容易”,然后将其传递给子级,这样他们就可以进行回调。我想保持孩子没有任何逻辑,只是渲染我发送的东西。
  • 孩子的@Output eventEmitter (angular.io/docs/ts/latest/api/core/index/Output-var.html) 会做你想做的事吗?如果父组件没有动态生成函数并且您希望它触发 addToCart 函数,您可以向子组件添加一个 @Output 并执行类似的操作:angular.io/docs/ts/latest/cookbook/…
猜你喜欢
  • 2016-08-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-17
  • 2019-05-30
  • 2017-08-30
  • 2017-05-31
  • 2017-11-29
相关资源
最近更新 更多