如何检测 Angular 中 @Input() 值何时发生变化?
我有一个父组件( CategoryComponent )、一个子组件( videoListComponent )和一个 ApiService。
其中大部分工作正常,即每个组件都可以访问 json api 并通过可观察对象获取其相关数据。
目前视频列表组件只获取所有视频,我想将其过滤为特定类别中的视频,我通过
@Input()
将 categoryId 传递给子组件来实现此目的。
CategoryComponent.html
<video-list *ngIf="category" [categoryId]="category.id"></video-list>
这有效,当父 CategoryComponent 类别发生变化时,categoryId 值会通过
@Input()
传递,但我需要在 VideoListComponent 中检测到这一点,并通过 APIService(使用新的 categoryId)重新请求视频数组。
在 AngularJS 中,我会做一个
$watch
变量。处理这个问题的最佳方法是什么?
实际上,在 angular2+ 中,有两种方法可以检测子组件中输入的变化并采取行动:
- 您可以使用 ngOnChanges() 生命周期方法 ,正如旧答案中提到的那样:
@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
演示示例:查看
这个 plunker
- 或者,您也可以使用 输入属性设置器 ,如下所示:
private _categoryId: string;
@Input() set categoryId(value: string) {
this._categoryId = value;
this.doSomething(this._categoryId);
}
get categoryId(): string {
return this._categoryId;
}
文档链接:查看 此处 。
演示示例:查看 这个 plunker 。
WHICH您应该使用哪种方法?
如果您的组件有多个输入,那么如果您使用 ngOnChanges(),您将在 ngOnChanges() 中一次性获取所有输入的所有更改。使用此方法,您还可以比较已更改的输入的当前值和以前的值,并采取相应的措施。
但是,如果您想在只有特定的单个输入发生变化时执行某些操作(并且您不关心其他输入),那么使用输入属性设置器可能会更简单。但是,这种方法没有提供内置方法来比较已更改输入的先前值和当前值(您可以使用 ngOnChanges 生命周期方法轻松完成此操作)。
编辑 2017-07-25:在某些情况下,角度变化检测可能仍不会触发
通常情况下,每当父组件更改传递给子组件的数据时,setter 和 ngOnChanges 的变化检测都会触发, 前提是数据是 JS 原始数据类型(字符串、数字、布尔值) 。但是,在以下情况下,它不会触发,您必须采取额外措施才能使其工作。
在您的组件中使用
ngOnChanges()
生命周期方法。
ngOnChanges is called right after the data-bound properties have been checked and before view and content children are checked if at least one of them has changed.
以下是 文档 。
在函数签名中使用
SimpleChanges
类型时,控制台、编译器和 IDE 中都出现了错误。为了避免出现错误,请在签名中使用
any
关键字。
ngOnChanges(changes: any) {
console.log(changes.myInput.currentValue);
}
编辑:
正如 Jon 在下面指出的那样,当使用括号表示法而不是点表示法时,您可以使用
SimpleChanges
签名。
ngOnChanges(changes: SimpleChanges) {
console.log(changes['myInput'].currentValue);
}