我有一个父组件( CategoryComponent ),一个子组件( videoListComponent )和一个ApiService .
我有大部分工作正常,即每个组件可以访问json api并通过observable获取其相关数据 .
目前视频列表组件只获取所有视频,我想将其过滤为特定类别中的视频,我通过 @Input()
将categoryId传递给孩子来实现这一点 .
CategoryComponent.html
<video-list *ngIf="category" [categoryId]="category.id"></video-list>
这有效,当父CategoryComponent类别更改时,categoryId值通过 @Input()
传递,但我需要在VideoListComponent中检测到这一点,并通过APIService(使用新的categoryId)重新请求视频数组 .
在AngularJS中,我会在变量上做 $watch
. 处理这个问题的最佳方法是什么?
9 回答
如果您不想使用ngOnChange实现og onChange()方法,您还可以通过 valueChanges event ,ETC订阅特定项目的更改 .
});
markForCheck()因为在此声明中使用而写入:
您还可以使用一个observable触发父组件(CategoryComponent)中的更改,并在子组件的订阅中执行您想要执行的操作 . (videoListComponent)
指南中有一个例子:
https://angular.io/guide/component-interaction#intercept-input-property-changes-with-ngonchanges
请尝试使用此方法 . 希望这可以帮助
Actually, there are two ways of detecting and acting up on when an input changes in the child component in angular2+ :
文档链接:ngOnChanges, SimpleChanges, SimpleChange
演示示例:查看this plunker
文档链接:看here .
演示示例:查看this plunker .
WHICH APPROACH SHOULD YOU USE?
如果您的组件有多个输入,那么,如果您使用ngOnChanges(),您将在ngOnChanges()中一次性获得所有输入的所有更改 . 使用此方法,您还可以比较已更改的输入的当前值和先前值,并相应地执行操作 .
但是,如果您只想在特定的单个输入发生更改时执行某些操作(并且您不关心其他输入),那么使用输入属性设置器可能会更简单 . 但是,此方法不提供内置方法来比较已更改输入的先前值和当前值(您可以使用ngOnChanges生命周期方法轻松完成) .
EDIT 2017-07-25: ANGULAR CHANGE DETECTION MAY STILL NOT FIRE UNDER SOME CIRCUMSTANCES
通常,只要父组件更改传递给子项的数据 provided that the data is a JS primitive datatype(string, number, boolean) ,就会触发setter和ngOnChanges的更改检测 . 但是,在以下情况下,它不会触发,您必须采取额外的操作才能使其正常工作 .
如果您使用嵌套对象或数组(而不是JS原始数据类型)将数据从Parent传递给Child,则更改检测(使用setter或ngchanges)可能不会触发,如用户的答案中所述:muetzerich . 对于解决方案,请查看here .
如果要改变角度上下文之外的数据(即外部),则angular将不知道更改 . 您可能必须在组件中使用ChangeDetectorRef或NgZone来使角度感知外部更改,从而触发更改检测 . 请参阅this .
在组件中使用
ngOnChanges()
生命周期方法 .这是Docs .
在函数签名中使用
SimpleChanges
类型时,我在控制台以及编译器和IDE中遇到错误 . 要防止出现错误,请在签名中使用any
关键字 .EDIT:
正如Jon在下面指出的那样,当使用括号表示法而不是点符号时,可以使用
SimpleChanges
签名 .最安全的选择是使用
@Input
参数的共享service instead . 此外,@Input
参数不会检测复杂嵌套对象类型中的更改 .一个简单的示例服务如下:
您可以在其他组件中使用类似的实现,并且您的所有组件将共享相同的共享值 .
我只想补充说,如果
@Input
值不是原始值,那么另一个名为DoCheck
的Lifecycle钩子很有用 .我有一个数组作为
Input
所以这不会在内容发生变化时触发OnChanges
事件(因为Angular的检查是'simple'并且不深,所以Array仍然是一个数组,即使数组上的内容已经改变) .然后,我实现了一些自定义检查代码,以决定是否要使用更改的Array更新我的视图 .