how to stop ngOnChanges Called before ngOnInit()

2020-02-08 05:31发布

问题:

In my angular application, i came up with a situation where ngOnchanges should only be called when the inputs are bound to changes. so, is there a way to stop the execution of ngOnChanges before ngOnInit. Is there a way to accomplish this. Thanks in Advance.

回答1:

You cannot prevent this behavior, but you can:

Use a Subject :

class Foo implements OnChanges,OnInit,OnDestroy{

  onChanges = new Subject<SimpleChanges>();

  ngOnInit(){
    this.onChanges.subscribe((data:SimpleChanges)=>{
      // only when inited
    });
  }
  ngOnDestroy(){
    this.onChanges.complete();
  }

  ngOnChanges(changes:SimpleChanges){
    this.onChanges.next(changes);
  }

}

Use a boolean property:

class Foo implements OnChanges,OnInit{

  initialized=false;

  ngOnInit(){
    // do stuff
    this.initialized = true;
  }

  ngOnChanges(changes:SimpleChanges){
    if(this.initialized){
      // do stuff when ngOnInit has been called
    }
  }

}

Use the SimpleChanges API

You can also check the SimpleChange.isFirstChange() method :

isFirstChange() : boolean Check whether the new value is the first value assigned.

class Foo implements OnChanges,OnInit{

  @Input()
  bar:any;

  ngOnInit(){
    // do stuff
  }

  ngOnChanges(changes:SimpleChanges){
    if(!changes["bar"].isFirstChange()){
      // do stuff if this is not the initialization of "bar"
    }
  }

}


回答2:

One method I have found that works is based on the fact that the input values all have a previous value property. If the input has not previously been set then that value will be CD_INIT_VALUE (as a string). So you can make a condition that your block of code in ngOnChanges should only run if the previous value is not CD_INIT_VALUE. Here's an example for your case where you're testing ALL the input values:

ngOnChanges(changes: SimpleChanges) {
  let initialized: boolean = true;
  for (let prop in changes) {
    if (changes[prop].previousValue.toString() === 'CD_INIT_VALUE') {
      initialized = false;
      //we can break here since if any item is not initialized
      //we will say the inputs are NOT initialized
      break;
    }
  }

  if (initialized) {
    //code you want to execute
  }    
}

There are probably more elegant solutions but I've found this works. This is probably too late to help you but may help others as when I googled this I found this question. The solution was something I figured out from debugging.



回答3:

In case it helps anyone here's an example of how I implemented the isFirstChange() solution suggested by @n00dl3 into my AngularJS app:

this.$onChanges = (changes) => {
    if (!changes.value.isFirstChange()) {
        // do stuff
    }
};


标签: angular