【问题标题】:How to wait for multiple input changes on child components?如何等待子组件的多个输入更改?
【发布时间】:2017-07-29 18:29:03
【问题描述】:

我正在尝试学习 Angular 2,并试图找出通过更改检测来实现某些功能的最佳方法。基本上我有这样的组件结构:

<parent-component>
    <child-component [input]="getData(1) | async"></child-component>
    <child-component [input]="getData(2) | async"></child-component>
</parent-component>

我想要做的是检测子组件的输入何时在同一个摘要周期中更新,然后在父组件类中调用一些函数。通过这种方式,我可以使用父组件一次处理多个更改,而不是一次处理每个更改。可以这样做吗?

【问题讨论】:

  • 您可以添加您想要的说明吗?我已经添加了答案,但它似乎不是你要找的

标签: angular


【解决方案1】:

将它们与 zip 或 combineLatest 结合起来

在组件中:

//now filtering out falsey values for getData
// make it .filter(v => v !== undefined) to ignore undefined specifically
dataOne$ = getData(1).filter(v => v);
dataTwo$ = getData(2).filter(v => v);

combined$ = Observable.zip(dataOne$, dataTwo$).do(e => console.log('do whatever you want here');

或者:

combined$ = Observable.combineLatest(dataOne$, dataTwo$).do(e => console.log('do whatever you want here');

在模板中:

<parent-component *ngIf="combined$ | async as combined">
  <child-component [input]="combined[0]"></child-component>
  <child-component [input]="combined[1]"></child-component>
</parent-component>

或者可能:

<parent-component >
  <child-component *ngFor="let input of combined$ | async" [input]="input"></child-component>
</parent-component>

第一个将使父子节点仅在组合至少解析一次时才实例化。

第二个将让父项立即实例化,但子项在两个项目都解决一次之前不会实例化。

第一个选项有一个微妙的好处,如果您使用 onpush 更改检测,父组件的更改检测将在每次异步更新中订阅它的 observable 时触发,但在第二种情况下不会触发,尽管无论如何,do 运算符都会触发。

只有两个 observables 更新时,zip 才会触发,并成对地为您提供值

combineLatest 将在其中一个触发时触发(在两者都触发一次之后)并为您提供另一个的最新值。

【讨论】:

  • 感谢您的帮助。我认为这几乎是我正在寻找的,我遇到的唯一问题是子组件上的输入最初可能是未定义的,因此调用 combineLatest 会导致错误。我可以通过子组件上的 ngOnChanges 检测输入何时更改,但我认为我需要一种方法将其传递给父组件以重新构建组合的 observable。你知道这是否可能吗?
  • 查看更新以忽略未定义的值,使用过滤器运算符忽略流的错误元素。如果您只想忽略 undefined 并接受 null 或 false 或 0,则将函​​数设为“v !== undefined”。如果您需要在父母和孩子之间来回传递信息,您应该使用共享数据服务来启用双向通信。
【解决方案2】:

您可以使用ngAfterViewChecked 生命周期挂钩。如Everything you need to know about change detection in Angular 中所述,所有挂钩都是变更检测的一部分。当 Angular 为当前组件运行变更检测时,子组件的绑定更新作为第一个操作执行。 ngAfterViewChecked 是当前视图组件变更检测完成时触发的钩子。

【讨论】:

    【解决方案3】:

    在您的 .ts 文件集变量中

    var data1;
    var data2;
    
    constructor()
    {
      getData1().then((d)=>{data1=d})
      getData2().then((d)=>{data2=d})
    }

    在你的 html 中做

    <parent-component>
        <child-component *ngIf="data1 && dat2" [input]="getData(1) | async"></child-component>
        <child-component *ngIf="data1 && dat2" [input]="getData(2) | async"></child-component>
    </parent-component>

    【讨论】:

    • 这仅在使用 Promise 时才有效,并且不会捕获检测两者何时同步更新的问题。
    【解决方案4】:

    在您的父组件中构建一个 AND 函数。这假设您的子组件上有 @Outputs 在提交输入时触发事件。

    <parent-component>
    <child-component (submitted)="increaseState()" [input]="getData(1) | async"></child-component>
    <child-component (submitted)="increaseState()" [input]="getData(2) | async"></child-component>
    </parent-component>
    

    父母.ts

    state = 0;
    
    increaseState(){
    this.state++
    }
    
    function()    {
      if(state === 2)   {
         *process values*
       }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-11-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-02
      • 2021-02-07
      • 1970-01-01
      • 2016-02-17
      相关资源
      最近更新 更多