想象一下Angular 2应用程序中的以下组件层次结构。
app.component
└── node.component
├── header.component
├── body.component
└── footer.component
该应用将呈现节点树。有一个根源' ngrx/store
中保存的节点,以反映树的状态。
app.component
获得"切片"在AppState
中保留的ngrx/store
,即根节点上的Observable
。
export class AppComponent {
rootNode: Observable<Node>;
constructor(private readonly store: Store<AppState>) {
this.rootNode = this.store.select(state => state.nodes);
}
}
app.component
使用rootNode
管道和async
呈现node.component
(请参阅上面的组件层次结构):
<app-node [node]="rootNode | async"></app-node>
node.component
收到Node
Input()
并使用以下三个组件呈现它:header.component
,body.component
,footer.component
。
@Component({
selector: 'app-node',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class NodeComponent {
@Input() node: Node;
constructor() {}
}
注意,node.component
视图 NOT 使用async
管道,因为它不呈现Observable
,而是正常的Node对象:< / p>
<node-header [node]="node"></node-header>
<node-body [node]="node"></node-body>
<node-footer [node]="node"></node-footer>
虽然这些子组件只呈现节点数据的子集,但它们接收整个节点@Input(),
,以便决定如何呈现它。
重要细节:所有三个组件都会创建一个FormGroup
,允许对节点进行编辑。但是,它们也呈现了可以编辑的相同值的视图,即
<input formControlName="title">
<p>Title {{ node.title }}</p>
由于header.component
,body.component
和footer.component
都做了几乎相同的事情,我只提供header.component
的大纲:
@Component({
selector: 'node-header',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class HeaderComponent implements OnInit {
@Input() node: Node;
@Input() headerForm: FormGroup;
constructor(private fb: FormBuilder) {}
ngOnInit() {
this.headerForm = this.fb.group({
title: [this.node.title]
});
}
}
FormBuilder
创建FormGroup
并绑定到从title
收到的节点的@Input()
属性。 <node-header>
将呈现用于编辑的表单控件和值:
<div [formGroup]="headerForm">
<input formControlName="title"name="title">
</div>
<p>Title {{ node.title }}</p>
node.component
和header.component
都使用OnPush
更改检测策略,因为节点数量可能会变得非常大。
问题/问题
编辑{{ node.title }}
控件时,input
未更新。我怀疑这是因为ngrx/store
中的值没有改变,因此app.component
中的Observable没有得到通知,并且更改检测不会运行。
<!-- Not updated when input control edited. -->
<app-node [node]="rootNode | async"></app-node>
我无法记住我在哪里阅读它,但如果某个组件更新了它自己的数据绑定属性,那么认为更改检测并不是必需的。但是,在此示例中,header.component
绑定到节点的属性 - 因此视图{{ node.title }}
未更新。为了更清楚,我已在header.component
添加了一些评论:
@Component({
selector: 'node-header',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class HeaderComponent implements OnInit {
@Input() node: Node;
@Input() headerForm: FormGroup;
constructor(private fb: FormBuilder) {}
ngOnInit() {
this.headerForm = this.fb.group({
// Binds to property of node.
// {{node.title}} won't update even thought it's "local".
title: [this.node.title]
});
}
}
我可以在此处做些什么来确保在用户进行修改时立即更新视图,并且稍后将更改推送到ngrx/store
?