2017-07-31 2 views
2

私たちが開発中の場合、角度ランは検出を2回変更します。次の例では、Angularランは検出を4回変更します。なぜこうなった?角度変化検出は4回の代わりに8回実行されます

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 {} 

上記のコードを実行すると、コンソールログが4回でなく8回実行されます。

+0

を取得する角度ゾーン –

+0

に各非同期タスクのために必要に応じて変化検出を何度でも実行しますAngularは最初の起動時に 'app.tick'を2回実行します – yurzui

+0

したがって、console.logは8回ではなく4回でなければなりません。 – ng2user

答えて

7

私はそれが文書化されたがappRef.tick角度の実行、追加のアプリケーション

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

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

をブートストラップするときそして、それは変化検出

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

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

を実行するために、メインハンドラを呼び出していません知っています

tick方法角実行中detectChanges方法

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

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

とDEVモードでchangeNoChanges

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

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

だから角度ランは、第INITに検出を4回変更します。

テンプレートで二回

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

をゲッターを使用するので、それが2回実行され、最終的にあなたは8つの通話

関連する問題