ค้นหาเว็บไซต์

javascript - Angular 2 วิธีส่งฟังก์ชันพร้อมพารามิเตอร์ไปยังคอมโพเนนต์ลูก?


คุณส่งฟังก์ชันจากคอมโพเนนต์พ่อแม่ไปยังคอมโพเนนต์ลูกอย่างถูกต้องเมื่อฟังก์ชันนั้นรับพารามิเตอร์อย่างไร?

ใน ngOnInit วิธีการกำหนดขอบเขตของฟังก์ชันเช่น:

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

ngOnInit ซึ่งตอนนี้ผิดพลาด

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

ในคอมโพเนนต์พาเรนต์ของฉัน ฉันมีฟังก์ชัน addToCart(id)

ฉันต้องการส่งฟังก์ชันนั้นไปยังคอมโพเนนต์ลูกของฉัน ซึ่งมีรายการของไอเท็ม และเมื่อคลิกปุ่ม ADD บนไอเท็มนั้น ฉันต้องการเรียกกลับ addToCart(item_id) ไปยังคอมโพเนนต์หลัก

คำตอบ #1

คำตอบของ @Maarek เป็นคำตอบที่ดี และน่าจะเป็นวิธีที่ 'ถูกต้อง' ในการทำ สิ่งที่ฉันนำเสนอที่นี่คือวิธีที่ง่ายกว่าในการสื่อสารโดยตรงจาก Child ไปยัง Parent

สิ่งที่คุณเสนอในโพสต์ต้นฉบับคือให้พ่อแม่ส่งวิธีการ callback ไปยังลูก เพื่อให้ลูกสามารถเรียกใช้งานมันพร้อมกับข้อมูลเมื่อเหมาะสม สำหรับการทำงานเฉพาะนี้ (ข้อมูลจากลูกไปยังพ่อแม่เมื่อมีการกระทำบางอย่างในลูก) การใช้ Events เป็นสิ่งที่เหมาะสม โดยใช้ 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);
  }
}

ผู้ปกครองจะเรียกสร้างคอมโพเนนต์แบบนี้:

<item id="1" (add)="addToList($event)"></item> ซึ่ง addToList() เป็นฟังก์ชันใน Parent ที่ทำงานสิ่งที่ callback ของคุณตั้งใจจะทำ $event คือข้อมูลที่ส่งมาจาก child (id)

คำตอบ #2

ที่นี่ไม่มีรายละเอียดมากนัก แต่จากสิ่งที่ผมกำลังเข้าใจ ผมคิดว่าสิ่งที่คุณต้องการคือบริการที่สามารถฉีดได้ (แสดงตัวอย่างที่นี่: https://angular.io/docs/ts/latest/tutorial/toh-pt4.html) เพื่อจัดการกับวัตถุข้อมูลที่ถูกแชร์ระหว่างคอมโพเนนต์ แทนที่จะพิมพ์โค้ดจำนวนมากที่นี่ (ซึ่งจะเห็นได้ดีกว่าที่หน้านั้นในบทเรียน) ผมจะอธิบายในสิ่งที่ผมคิดว่าคุณพยายามจะทำและวิธีที่ผมจะทำมัน

โมเดลข้อมูลร้านค้าทั้งหมดสามารถจัดการผ่านบริการได้ (อาจเป็น store.service.ts) ซึ่งจะมีฟังก์ชัน CRUD ของคุณที่เปิดให้ใช้งานสำหรับคุณสมบัติต่างๆ ของโมเดลร้านค้า รายการที่คุณกำลังเพิ่มตรงนี้ควรมี getter สาธารณะที่คืนค่า observable ของรายการในบริการ รวมถึงฟังก์ชันสาธารณะสำหรับการเพิ่มและลบจากรายการด้วย อะไรประมาณนี้:

@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 ให้แน่ใจว่าได้ส่งค่าผ่าน async pipe *ngFor="List | async" ไม่เช่นนั้นคุณอาจหัวเสียพยายามหาว่าทำไมถึงเกิดข้อผิดพลาดขึ้น

บทความนี้ช่วยฉันได้มากกับเรื่องนี้เช่นกัน (แม้ว่าฉันอาจจะแนะนำให้หลีกเลี่ยงการใช้ immutable ในตอนแรกจนกว่าคุณจะคุ้นเคยกับ Angular 2 อย่างสมบูรณ์): http://blog.angular-university.io/how-to-build-angular2-apps-using-rxjs-observable-data-services-pitfalls-to-avoid/