9

我一直在寻找这种行为的某种原因,子组件“Param”中的 Input() 属性的值没有在正确的时间更新,我需要使用更新的值作为参数调用服务。通过单击“更新子值”按钮,首先显示 LOG B(带有旧值),然后显示 LOG A(LOG A 它位于属性的设置器中)。

父组件

@Component({
  selector: 'parent',
  template: `
     <child #child [param]="parentParam"></child>
     <button (click)="updateChildValue()">Update child value</button>
`})
export class Parent {
  @ViewChild('child') child: Child;
  public parentParam: number;

  public updateChildValue() {
    this.parentParam = 9;
    this.child.showParam();
  }
}

子组件

@Component({
   selector: 'child',
   template: '' })

export class Child {

   private _param: number;

   public get param() : number {
       return this._param;
   }

   @Input('param')
   public set param(v : number) {
      this._param  = v;
      console.log('LOG A');
      console.log(this.param);        
   }

   public showParam() {
      console.log('LOG B');
      console.log(this.param);
      //I need to call a service using the latest value of param here...
   }
}

期望的行为是首先更新参数的值,然后将该值用作服务的参数。LOG A 然后 LOG B

4

3 回答 3

12

Using@Input()意味着您依赖 Angular2 机制来传播值更改,这意味着您不应该期望您的更改立即生效。事实上,您this.parentParam = 9;将经历一个完整的 Angular2 周期来更新您孩子的param,并且该showParam()函数将始终首先执行。

为了完成您的任务,您有 2 个选择:

1)直接将参数添加到您的showParam,如:

// child component
public showParam(newVal: number) {
  this._param = newVal;
  // do your service call here
}

// parent component
public updateChildValue()
{
  this.parentParam = 9;
  this.child.showParam(9);
}

2)利用ngOnChanges您的Child组件。每当任何@Input. 但是,如果您有超过 1 个输入,这可能会出现问题。

ngOnChanges(changes) {
  console.log(this.param); // new value updated
}
于 2016-10-26T23:43:36.490 回答
4

我认为这是比当前接受的答案更好的答案:

实现这一点的 Angular2+ 方法是使用 ngOnChanges 生命周期钩子:

父组件:

@Component({
  selector: 'parent',
  template: `
     <child #child [param]="parentParam"></child>
     <button (click)="updateChildValue()">Update child value</button>
`})
export class Parent {
  @ViewChild('child') child: Child;
  public parentParam: number;

  public updateChildValue() {
    this.parentParam = 9;
    this.child.showParam();
  }
}

子组件:

import { OnChanges, SimpleChanges, SimpleChange } from '@angular/core'

@Component({
   selector: 'child',
   template: '' })

export class Child implements OnChanges {

   @Input() param: number;  

   

   public showParam() {
      console.log('LOG B');
      console.log(this.param);
      //I need to call a service using the latest value of param here...
   }
   
   ngOnChanges(changes: SimpleChanges) {
     const c: SimpleChange = changes.param;
     this.param = c;
   }
}
于 2017-07-13T12:24:40.450 回答
-1

只需在父组件中添加一个加载标志,并在 *ngIf 中使用它来显示子组件,如下所示:

@Component({
  selector: 'parent',
  template: `
     <child *ngIf="!loading" #child [param]="parentParam"></child>
     <button (click)="updateChildValue()">Update child value</button>
`})
export class Parent {
  @ViewChild('child') child: Child;
  public parentParam: number;
  loading: boolean;

  public updateChildValue() {
    this.loading = true;
    this.parentParam = 9;
    this.loading = false;
    this.child.showParam();
  }
}

这样,每次加载设置为 false 时,都会使用最新数据初始化子元素。

经过大量研究后,我发现这是最干净/最高效的解决方案,并且避免了与变更检测和设置器的搏斗。

于 2020-01-24T19:19:16.203 回答