angular2 中注入服务 属性 的变更检测
Change detection on injected service's property in angular2
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
成员是人为设计的,当然可以在模板本身中完成,但是为了我的问题,假设 updateAddedItemsString
可以做很多更复杂的事情来更新ListComponent
.
的单独成员
提前致谢!
在您的服务中使用 BehaviorSubject
<Item[]>
,并让您的 ListComponent 订阅对该可观察数组的更改:
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();
}
}
每次调用 next()
时我都会发出整个数组。这确保以后订阅 BehaviorSubject 的任何其他组件都将获得完整列表。如果您没有该要求,则可以在调用 addItem()
时仅发出新值。
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
成员是人为设计的,当然可以在模板本身中完成,但是为了我的问题,假设 updateAddedItemsString
可以做很多更复杂的事情来更新ListComponent
.
提前致谢!
在您的服务中使用 BehaviorSubject
<Item[]>
,并让您的 ListComponent 订阅对该可观察数组的更改:
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();
}
}
每次调用 next()
时我都会发出整个数组。这确保以后订阅 BehaviorSubject 的任何其他组件都将获得完整列表。如果您没有该要求,则可以在调用 addItem()
时仅发出新值。