admin管理员组

文章数量:1424902

I know that if we are on development Angular runs change detection twice. In the following example, Angular runs change detection four times. Why is this happening?

class Category {
  constructor( private _id ) {
  }

  get id() {
    console.log('id');
    return this._id;
  }

}

@Component({
  selector: 'app-select',
  template: `
      <select class="form-control">
        <option *ngFor="let option of options;" [value]="option.id">{{option.id}}</option>
      </select>
  `,
})
export class SelectComponent {
  @Input() options;
}

@Component({
  selector: 'my-app',
  template: `
    <app-select [options]="options"></app-select>
  `,
})
export class App {
  options = [new Category(1)]
}

@NgModule({
  imports: [ BrowserModule ],
  declarations: [ App, SelectComponent ],
  bootstrap: [ App ]
})
export class AppModule {}

If you run the code above you will see that the console log runs eight times instead four.

I know that if we are on development Angular runs change detection twice. In the following example, Angular runs change detection four times. Why is this happening?

class Category {
  constructor( private _id ) {
  }

  get id() {
    console.log('id');
    return this._id;
  }

}

@Component({
  selector: 'app-select',
  template: `
      <select class="form-control">
        <option *ngFor="let option of options;" [value]="option.id">{{option.id}}</option>
      </select>
  `,
})
export class SelectComponent {
  @Input() options;
}

@Component({
  selector: 'my-app',
  template: `
    <app-select [options]="options"></app-select>
  `,
})
export class App {
  options = [new Category(1)]
}

@NgModule({
  imports: [ BrowserModule ],
  declarations: [ App, SelectComponent ],
  bootstrap: [ App ]
})
export class AppModule {}

If you run the code above you will see that the console log runs eight times instead four.

Share Improve this question asked Jul 31, 2017 at 9:34 ng2userng2user 2,0876 gold badges25 silver badges31 bronze badges 11
  • change detection runs as many times as needed for each async task in the Angular zone – Max Koretskyi Commented Jul 31, 2017 at 9:35
  • Angular runs app.tick twice on first start – yurzui Commented Jul 31, 2017 at 9:38
  • So it should console.log four times, not eight. – ng2user Commented Jul 31, 2017 at 9:39
  • two for each {{options.id}} bindings. – ng2user Commented Jul 31, 2017 at 9:39
  • 1 It should log 8 times app.tick (detectChanges, checkNoChanges), app.tick (detectChanges, checkNoChanges) – yurzui Commented Jul 31, 2017 at 9:40
 |  Show 6 more ments

1 Answer 1

Reset to default 11

I know it is not documented but angular runs additional appRef.tick when bootstraping application

 private _loadComponent(ponentRef: ComponentRef<any>): void {
    this.attachView(ponentRef.hostView);
    this.tick();

https://github./angular/angular/blob/4.3.x/packages/core/src/application_ref.ts#L540

And then it calls main handler to run change detection

this._zone.onMicrotaskEmpty.subscribe(
    {next: () => { this._zone.run(() => { this.tick(); }); }});

https://github./angular/angular/blob/4.3.x/packages/core/src/application_ref.ts#L445

During the tick method angular runs detectChanges method

this._views.forEach((view) => view.detectChanges()); 

https://github./angular/angular/blob/master/packages/core/src/application_ref.ts#L561

and in dev mode changeNoChanges

if (this._enforceNoNewChanges) {
    this._views.forEach((view) => view.checkNoChanges());
}

https://github./angular/angular/blob/master/packages/core/src/application_ref.ts#L563

So angular runs change detection 4 times on first init.

Since you use getter twice in template

[value]="option.id">{{option.id}}

it will be executed twice and finally you will get 8 calls

本文标签: javascriptAngular change detection runs eight times instead fourStack Overflow