2

ここでは Angular1 のベテランで、angular2 を学ぼうとしています。MyStateそれ自体とそのサブコンポーネントに注入される状態サービス (以下) を持つコンポーネントがあります。次のように、サービスの状態の変化を監視してから、最上位コンポーネントの別のメンバーを更新したいと考えています。

import { Component, Input } from '@angular/core';

class Item {
  constructor(public name: string) {}
}

class MyState {
  selectedItems: Item[] = [];
  addItem(item: Item) {
    this.selectedItems.push(item);
  }
}

// subcomponent
@Component({
  selector: '[item]',
  template: `
    <!-- state changed from subcomponent: -->
    <button (click)="state.addItem(model)">
      select item {{model.name}}
    </button>
  `
})
class ItemComponent {
  @Input() model: Item;
  constructor(private state: MyState){}
}

// main component
@Component({
  selector: 'items',
  template: `
    <h1> Available Items: </h1>
    <ul>
      <li *ngFor="let item of items" item [model]="item"></li>
    </ul>
    <h1> Added Items: </h1>
    <p>{{ addedItemsString }}</p>
  `,
  providers: [MyState],
  directives: [ItemComponent]
})
class ListComponent {
  @Input() items: Item[];
  private addedItemsString: string = '';

  constructor(private state: MyState) {
    // listen for changes to this.state.selectedItems to   
    // call this.updateAddedItemsString
  }

  updateAddedItemsString () {
    this.addItemsString = this.state.selectedItems.map(i => i.name).join(', ');
  }
}

私の質問は、ListComponent コンストラクターで疑似コードをどのように実装すればよいですか?

確かに、メンバーは工夫されており、確かにテンプレート自体で行うことができますが、私の質問のために、の別のメンバーを更新するより複雑なことを行うことができるaddItemsStringと仮定します.updateAddedItemsStringListComponent

前もって感謝します!

4

1 に答える 1

2

サービスでa を使用し、ListComponent にその監視可能な配列への変更をサブスクライブさせます。BehaviorSubject<Item[]>

class MyState {
  private _selectedItems: Item[] = [];
  private _selectedItemsSource = new BehaviorSubject<Item[]>(this._selectedItems);
  selectedItems$ = this._selectedItemsSource.asObservable();
  addItem(item: Item) {
    this._selectedItems.push(item);
    this._selectedItemsSource.next(this._selectedItems);
  }
}

@Component({
  selector: 'items',
  template: `<h1> Available Items: </h1>
    <ul>
      <li *ngFor="let item of items" item [model]="item"></li>
    </ul>
    <h1> Added Items: </h1>
    <div>{{ addedItemsString }}</div>`,
  providers: [MyState],
  directives: [ItemComponent]
})
class ListComponent {
  @Input() items: Item[];
  private addedItemsString: string = '';
  constructor(private state: MyState) {}
  ngOnInit() {
    this.subscription = this.state.selectedItems$.subscribe(
      items => this.addedItemsString = items.map(i => i.name).join(', '));
  }
  ngOnDestroy() {
    // prevent memory leak when component is destroyed
    this.subscription.unsubscribe();
  }
}

Plunker

next()呼び出されるたびに配列全体を発行します。これにより、後で BehaviorSubject をサブスクライブする他のコンポーネントが完全なリストを取得できるようになります。その要件がない場合は、addItem()が呼び出されたときに単純に新しい値のみを発行できます。

于 2016-07-27T02:46:18.047 に答える