我有一个父组件(CategoryComponent)、一个子组件(videoListComponent)和一个APIService。
我的大部分工作都很好,即每个组件都可以访问json api,并通过Observables获取其相关数据。
当前video list组件只获取所有视频,我想将其筛选为特定类别中的视频,我通过@input()
将categoryId传递给子对象实现了这一点。
CategoryComponent.html
<video-list *ngIf="category" [categoryId]="category.id"></video-list>
这样可以工作,当父CategoryComponent类别更改时,categoryId值将通过@input()
传递,但我需要在VideoListComponent中检测到这一点,并通过APIService(使用新的categoryId)重新请求Video数组。
在AngularJS中,我会对变量执行$watch
。处理这件事最好的方法是什么?
实际上,当Angular2+中的子组件中的输入发生变化时,有两种方法可以检测和执行:
@Input() categoryId: string;
ngOnChanges(changes: SimpleChanges) {
this.doSomething(changes.categoryId.currentValue);
// You can also use categoryId.previousValue and
// categoryId.firstChange for comparing old and new values
}
文档链接:ngOnChanges,SimpleChanges,simplechange
演示示例:看这个柱塞
private _categoryId: string;
@Input() set categoryId(value: string) {
this._categoryId = value;
this.doSomething(this._categoryId);
}
get categoryId(): string {
return this._categoryId;
}
文档链接:看这里。
演示示例:看看这个柱塞。
你应该使用哪种方法?
如果您的组件有几个输入,那么,如果您使用ngOnChanges(),您将在ngOnChanges()中一次获得所有输入的所有更改。使用此方法,您还可以比较已更改的输入的当前值和以前的值,并相应地采取操作。
但是,如果您想在只有特定的单个输入更改时执行某些操作(而您不关心其他输入),那么使用输入属性设置器可能会更简单。但是,这种方法没有提供一种内置的方式来比较更改的输入的以前值和当前值(您可以通过ngOnChanges生命周期方法轻松地完成这一操作)。
编辑2017-07-25:角度变化探测在某些情况下仍可能不开火
通常情况下,只要父组件更改它传递给子组件的数据,那么setter和ngOnChanges的更改检测都将触发,前提是数据是JS基元数据类型(字符串、数字、布尔)。但是,在下面的场景中,它不会开火,您必须采取额外的操作才能使它工作。
>
如果使用嵌套对象或数组(而不是JS基元数据类型)将数据从父级传递到子级,则更改检测(使用setter或ngchanges)可能不会触发,正如用户muetzerich的回答中所述。如需解决方案,请参阅此处。
如果您在angular上下文之外(即外部)更改数据,那么angular将不知道更改。您可能必须在组件中使用ChangeDetectorRef或NgZone来对外部更改进行角度感知,从而触发更改检测。请参阅此。
在组件中使用ngonchanges()
生命周期方法。
在检查数据绑定属性之后,如果至少有一个属性发生了更改,则在检查视图和内容子项之前调用ngOnChanges。
这是文件。