开发者问题收集

如何检测 Angular 中 @Input() 值何时发生变化?

2016-07-25
681531

我有一个父组件( 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 变量。处理这个问题的最佳方法是什么?

3个回答

实际上,在 angular2+ 中,有两种方法可以检测子组件中输入的变化并采取行动:

  1. 您可以使用 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

  1. 或者,您也可以使用 输入属性设置器 ,如下所示:
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 原始数据类型(字符串、数字、布尔值) 。但是,在以下情况下,它不会触发,您必须采取额外措施才能使其工作。

  1. 如果您使用嵌套对象或数组(而不是 JS 原始数据类型)将数据从 Parent 传递到 Child,则更改检测(使用 setter 或 ngchanges)可能不会触发,正如用户 muetzerich 在回答中提到的那样。有关解决方案,请查看 此处

  2. 如果您在 angular 上下文之外(即外部)改变数据,那么 angular 将不知道这些变化。您可能必须在组件中使用 ChangeDetectorRef 或 NgZone,以使 angular 了解外部变化并从而触发变化检测。请参阅

Alan C. S.
2017-06-21

在您的组件中使用 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.

以下是 文档

muetzerich
2016-07-25

在函数签名中使用 SimpleChanges 类型时,控制台、编译器和 IDE 中都出现了错误。为了避免出现错误,请在签名中使用 any 关键字。

ngOnChanges(changes: any) {
    console.log(changes.myInput.currentValue);
}

编辑:

正如 Jon 在下面指出的那样,当使用括号表示法而不是点表示法时,您可以使用 SimpleChanges 签名。

ngOnChanges(changes: SimpleChanges) {
    console.log(changes['myInput'].currentValue);
}
Darcy
2016-10-06