如何正确处理依赖ViewChild和Angular 2中可观察到的数据的组件上的更改检测
How do I properly handle change detection on a component that relies on a ViewChild and data from an observable in Angular 2?
因此,目前,我有一个组件可以放入一个更大的面板中,用于呈现节点的直接父关系和子关系的图形。该组件应该在每次node_id
输入从外部更改时刷新其图形。
我已经包含了代码的简化版本。
@Component({
selector: 'relations',
template: `
<div [class]="'panel panel-' + (_loading ? 'default' : 'primary')">
<div class="panel-heading">Child relations</div>
<div class="panel-body">
<div class="loading" *ngIf="_loading" style="text-align: center">
<img src="./loading.gif" height="100px" width="100px" />
</div>
<div class="graph_container" [style.display]="_loading ? 'none': 'block'" #my_graph></div>
</div>
</div>
`
})
export class GraphComponent implements OnChanges {
@Input('node_id') node_id;
@ViewChild('my_graph') graphDiv;
private _loading: boolean = true;
private _current_node: Node;
private _parent: Node;
private _children: Node[];
constructor(
private _nodeService: NodeService
) {}
ngOnChanges(changes){
this.getRelations();
}
getRelations() {
this._loading = true;
Observable.combineLatest(
this._nodeService.getEvent(this.node_id),
this._nodeService.getChildren(this.node_id),
this._nodeService.getParent(this.node_id)
).subscribe(v => {
this._current_node = v[0];
this._children = v[1];
this._parent = v[2];
this._loading = false
this.renderGraph();
});
}
renderGraph() {
...
}
}
现在我遇到的问题是种族状况;CCD_ 2方法依赖于CCD_。因此,当可观察到的解析时,它可能会在@ViewChild
组件初始化之前尝试调用renderGraph()
。
我试着通过做一些事情来使用生命周期挂钩,比如:
ngAfterViewInit(){
if (!this._loading){
this.renderGraph();
}
}
只有当可观察到的在加载视图之前完成时,这才有帮助,并且如果视图首先完成渲染,则不会导致渲染任何图形。
所以我的问题是,我如何才能正确地实现我想要的?也就是说,响应于node_id
的改变,在可观察的解析之后重新渲染图。
我是Angular 2的新手(通常是前端),我的直觉告诉我,我没有以预期的方式使用可观察到的,但我很难找到任何与我想要的相似的例子。
如有任何帮助/指导/建议,我们将不胜感激。
谢谢!
我会使用BehaviorSubject
,它只是Observable的一种特殊类型。文档中的代码段:
它存储向消费者发出的最新值,每当新的Observer订阅时,它将立即从BehaviorSubject接收"当前值"。
首选BehaviorSubject
的原因是,无论订阅实际发生在何时,它都会发出最后一个node_id
值。如果它是在viewInit之前设置的。此外,因为它总是具有最新的值,所以我们不需要在GraphComponent
上具有node_id
属性。我们只需要一个setter,它会将传递的值发送给订阅者,并自动将其保存在主题上,这样每个新订阅者都会获得当前值。
import {BehaviorSubject} from 'rxjs/BehaviorSubject';
...
export class GraphComponent implements OnChanges {
@ViewChild('my_graph') graphDiv;
...
private _nodeIdSubject = new BehaviorSubject(-1);
constructor(...) {}
@Input('node_id')
set node_id(id){ // this is the same as ngOnChanges but will only be triggered if node_id changed
this._nodeIdSubject.next(id);
}
ngAfterViewInit(){ // subscribe to node_id changes after view init
this._nodeIdSubject.filter(n=> n > -1).subscribe(nodeId=> this.getRelations(nodeId));
}
getRelations(nodeId) {
...
}
renderGraph() {
...
}
}
这可能不是最好的方法,但我喜欢它,因为现在您有了一个可以自由操作的node_id
流。
- React Native通过Navigator将用户输入数据传递到选项卡栏IOS中的组件
- React-将jSON数据传递给子组件的子组件
- 如何在ReactJs中渲染子组件时重新加载子组件的数据
- 在reactjs组件中预加载数据
- 具有大型数据集的组件仅在 IE11/Edge 上运行缓慢
- 使用数据数组创建多个类似组件
- 如何正确处理依赖ViewChild和Angular 2中可观察到的数据的组件上的更改检测
- Angular2路由-将数据从父组件传递到子组件
- 编辑组件中的Vuejs数据
- 在多个react.js组件中呈现json数据
- 通过使用此组件,检索父类数据
- 如何创建一个组件,我可以设置在 Angular 2 中的属性中获取 URL 数据
- 如何使用Vue.js(使用Vueify)通过组件显示数据
- Vue.js从另一个组件获取数据
- Sencha Touch:如何在setData()之后刷新组件的数据
- 如何更新angular2中组件之间的事件数据
- 如何访问Vue.js中深度嵌套的子组件中的数据
- 将数据传回父组件的ReactJS组件无法工作
- 如何处理需要子组件状态的Meteor数据
- 根据location.hash传递的数据重新呈现ReactJS嵌套的子组件