我正在尝试将异步数据(可观察的数据)从父级传递到子级组件,但是似乎更改未在子级组件上进行,我不确定为什么。
我有一个使用BehaviourSubject
的(简体)服务:
@Injectable()
export class MyService {
private _items: BehaviorSubject<any[]> = new BehaviorSubject([]);
public items: Observable<any[]> = this._items.asObservable();
list() {
this.http.get('...').subscribe(items => {
this._items.next(items);
})
}
}
(正在我的应用程序的其他位置定期调用list()
函数来更新数据。)
然后我有了一个父组件:
@Component({
selector: 'parent',
templateUrl: '<child [items]="myService.items | async"></child>',
})
export class Parent {
constructor(public myService: MyService) {
}
}
和一个孩子:
@Component({
selector: 'child',
templateUrl: '<ul><li *ngFor="item of _items">{{item.name}}</li></ul>',
})
export class Parent implements OnChanges {
@Input() items;
_items = [];
constructor() {
}
ngOnChanges(changes: SimpleChanges) {
console.log('changes', changes);
this._items = changes.items;
}
}
我的理解是,使用async
会自动订阅/取消订阅我的Observable,并将所有新数据传递给我的子组件。当有新数据输入时,我的子组件应该检测ngOnChanges
中的那些更改并将其打印出来。
答案 0 :(得分:2)
我可以建议您对代码进行一些更改:
父母:
@Component({
selector: 'app-parent',
changeDetection: ChangeDetectionStrategy.OnPush,
templateUrl: '<app-child [items]="(myService.items | async)"></app-child>',
})
export class Parent {
constructor(public myService: MyService) {
}
}
-在[items]分配中添加了括号
孩子:
@Component({
selector: 'app-child',
changeDetection: ChangeDetectionStrategy.OnPush,
templateUrl: '<ul><li *ngFor="item of _items">{{item.name}}</li></ul>',
})
export class Child implements OnChanges {
@Input() items;
_items = [];
constructor() {
}
ngOnChanges(changes: SimpleChanges) {
console.log('changes', changes);
console.log(this.items);
this._items = changes.items;
}
}
答案 1 :(得分:2)
您快到了:-)。我只有几点提示...
@Injectable()
export class MyService {
// Post-fixing your observable variables with `$` will make it easy to see them at the first glance.
private _items$: BehaviorSubject<any[]> = new BehaviorSubject([]);
get items$(): Observable<any[]> {
// BehaviorSubject is an Observable as well
return this._items$;
// Or if you want to be safe and not leak your abstraction, use what you did...
return this._items$.asObservable();
}
list() {
// BehaviorSubject can subscribe itself
this.http.get('...').subscribe(this._items$);
}
}
我会将可观察值存储在您的父项字段中。如果您不需要该组件中其他任何地方的服务,为什么要保留引用。
@Component({
selector: 'parent',
templateUrl: '<child [items]="items$ | async"></child>',
})
export class ParentComponent {
items$: Observable<any[]>;
constructor(myService: MyService) {
this.items$ = myService.items$;
}
}
在这种情况下,您不需要ngOnChanges
,因为您可以输入属性。如果不需要日志记录,则可以完全放弃访问器。
@Component({
selector: 'child',
templateUrl: '<ul><li *ngFor="item of items">{{item.name}}</li></ul>',
})
export class ChildComponent{
private _items = [];
@Input() set items(_items) {
console.log('items', _items);
this._items = _items;
}
get items() {
return this._items;
}
}
您的异步数据处理方法很好。在我看来,将关注点分离到'smart' and 'dumb' components中是可行的方法。
希望这会有所帮助:-)