如何检测 @Input() 值何时在 Angular 中发生变化? [英] How to detect when an @Input() value changes in Angular?

查看:41
本文介绍了如何检测 @Input() 值何时在 Angular 中发生变化?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个父组件 (CategoryComponent)、一个子组件 (videoListComponent) 和一个 ApiService.

I have a parent component (CategoryComponent), a child component (videoListComponent) and an ApiService.

我的大部分工作都很好,即每个组件都可以访问 json api 并通过 observables 获取其相关数据.

I have most of this working fine i.e. each component can access the json api and get its relevant data via observables.

目前视频列表组件只获取所有视频,我想将其过滤为特定类别的视频,我通过通过 @Input() 将 categoryId 传递给孩子来实现这一点.

Currently video list component just gets all videos, I would like to filter this to just videos in a particular category, I achieved this by passing the categoryId to the child via @Input().

类别组件.html

<video-list *ngIf="category" [categoryId]="category.id"></video-list>

这有效,当父 CategoryComponent 类别更改时,categoryId 值会通过 @Input() 传递,但我需要在 VideoListComponent 中检测到这一点并通过 APIService 重新请求视频数组(使用新的 categoryId).

This works and when the parent CategoryComponent category changes then the categoryId value gets passed through via @Input() but I then need to detect this in VideoListComponent and re-request the videos array via APIService (with the new categoryId).

在 AngularJS 中,我会对变量执行 $watch.处理此问题的最佳方法是什么?

In AngularJS I would have done a $watch on the variable. What is the best way to handle this?

推荐答案

实际上,当 angular2+ 中的子组件中的输入发生变化时,有两种检测和操作的方法:

  1. 您可以使用 ngOnChanges() 生命周期方法,如旧答案中所述:
  1. You can use the ngOnChanges() lifecycle method as also mentioned in older answers:

    @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. 或者,您也可以使用输入属性设置器,如下所示:
  1. Alternately, you can also use an input property setter as follows:

    private _categoryId: string;
    
    @Input() set categoryId(value: string) {
    
       this._categoryId = value;
       this.doSomething(this._categoryId);
    
    }
    
    get categoryId(): string {
    
        return this._categoryId;
    
    }

文档链接:查看这里.

演示示例:查看这个plunker.

您应该使用哪种方法?

如果您的组件有多个输入,那么,如果您使用 ngOnChanges(),您将在 ngOnChanges() 中一次获得所有输入的所有更改.使用这种方法,您还可以比较已更改的输入的当前值和先前值,并采取相应的措施.

If your component has several inputs, then, if you use ngOnChanges(), you will get all changes for all the inputs at once within ngOnChanges(). Using this approach, you can also compare current and previous values of the input that has changed and take actions accordingly.

但是,如果您只想在特定的单个输入更改时执行某些操作(并且您不关心其他输入),那么使用输入属性设置器可能会更简单.但是,这种方法没有提供一种内置方式来比较已更改输入的先前值和当前值(您可以使用 ngOnChanges 生命周期方法轻松实现).

However, if you want to do something when only a particular single input changes (and you don't care about the other inputs), then it might be simpler to use an input property setter. However, this approach does not provide a built in way to compare previous and current values of the changed input (which you can do easily with the ngOnChanges lifecycle method).

EDIT 2017-07-25:在某些情况下,角度变化检测可能仍然不会触发

通常,每当父组件更改其传递给子组件的数据时,都会触发 setter 和 ngOnChanges 的更改检测,前提是数据是 JS 原始数据类型(字符串、数字、布尔值).但是,在以下情况下,它不会触发,您必须采取额外的措施才能使其工作.

Normally, change detection for both setter and ngOnChanges will fire whenever the parent component changes the data it passes to the child, provided that the data is a JS primitive datatype(string, number, boolean). However, in the following scenarios, it will not fire and you have to take extra actions in order to make it work.

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

如果你在 angular 上下文之外(即外部)改变数据,那么 angular 不会知道这些变化.您可能必须在组件中使用 ChangeDetectorRef 或 NgZone 来使角度感知外部变化,从而触发变化检测.请参阅.

If you are mutating data outside of the angular context (i.e., externally), then angular will not know of the changes. You may have to use ChangeDetectorRef or NgZone in your component for making angular aware of external changes and thereby triggering change detection. Refer to this.

这篇关于如何检测 @Input() 值何时在 Angular 中发生变化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆