1

これは、Angular 2 の変更検出がどのように機能するかについての私自身の誤解かもしれませんが、コンポーネントが、またはChangeDetectionStrategyに設定されている場合、そのコンポーネントは、コンポーネントがインスタンス化されたときに一度だけ変更をチェックすることを期待していました。そのようには起こらないようです。CheckedCheckOnceDetached

import {Component, OnInit, ChangeDetectionStrategy} from 'angular2/core'

@Component({
  selector: 'my-app',
  providers: [],
  template: `
    <div>
      <button 
        (click)="onClick($event)" 
        [class.thing]="hasThingClass()">Update</button>
    </div>
  `,
  changeDetection:ChangeDetectionStrategy.CheckOnce,
  styles: [`
    .thing { background-color: red }
  `]
})

export class App implements OnInit {

  public hasThing:Boolean = false;

  onClick() {
    this.hasThing = !this.hasThing;
  }

  hasThingClass(e) {
    return this.hasThing;
  }

}

クリックすると、hasThingプロパティが切り替わると思っていましたが、ビューが更新されるとは思っていませんでした。たまたま、ビューが更新されます。ChangeDetectionStrategyもに設定されている場合に発生しDetachedます。

http://plnkr.co/edit/2hHdt2BDpj419Z32iPjJ?p=preview

ここで何が欠けていますか?ビューが更新される正確な原因は何ですか? hasThingプロパティを更新するかどうかに関係なく、値が変更されたかどうかに関係なく、クリックするとビューが更新されます。

4

2 に答える 2

6

ChangeDetectionStrategy の設定に関係なく、Angular はいつでもコンポーネントの変更をチェックします。

  • コンポーネントがイベントを発生させる
  • オブザーバブルがイベントを発生させ、非同期パイプがそのオブザーバブルのビューで使用されます

アイデアは...コンポーネントがイベントをトリガーした場合、またはバインドされた監視可能な値が変更された場合、おそらくそのビューを更新する必要があります。

于 2016-03-23T14:12:07.620 に答える
4

これが理解に役立つことを願っています:)

http://plnkr.co/edit/sM8CCSl8hXyRVAaTZH4N?p=preview

サービスでシミュレートする非同期イベントがあるとします。

import { Injectable } from 'angular2/core';

@Injectable()
export class DataProvider {
  data = 1;
  constructor() {
    // async data change simulation
    setInterval(() => {
      this.data = this.data * 2;
    }, 500);
  }
}

angular が zone api を介して非同期イベントの変更を検出すると、ゾーンはそのコンテキストで非同期イベントが発生したことを通知し、それを angular 変更検出 api に伝達して実際のビューとコンポーネント間のチェックを行います。以下の例では、変更以降のことがわかります。検出動作は変更されません角度は常にビューを更新しています:

import {
  Component
} from 'angular2/core';
import { bootstrap } from 'angular2/platform/browser';
import { DataProvider } from './data-provider';
import { TriggerDataChange } from './data-change-trigger';

@Component({
  selector: 'app',
  template: `
    <div>Live Update: {{dataProvider.data}} </div>
    <data-change-trigger></data-change-trigger>
  `,
  providers: [DataProvider],
  directives: [TriggerDataChange]
})
class App {
  constructor(private dataProvider:DataProvider) {}
}

bootstrap(App);

ChangeDetectionStrategy が CheckOnce angular に設定されているため、変更検出の動作が変更されたシナリオ 2 では、コンポーネントの初期化プロセスで変更検出が 1 回だけトリガーされます。その場合、変更を手動でトリガーしてビューを更新する必要があります。この場合はイベント バインディングによって行われます。

import {
  Component,
  ChangeDetectionStrategy, 
  ChangeDetectorRef
} from 'angular2/core';
import { DataProvider } from './data-provider';

@Component({
  selector: 'data-change-trigger', 
  changeDetection: ChangeDetectionStrategy.CheckOnce,
  template: `
    Trigger update: 
    <button (click)="update($event)">Update</button>
    <div>{{dataProvider.data}}</div>
  `
})
export class TriggerDataChange {

  constructor(
    private ref: ChangeDetectorRef, 
    private dataProvider:DataProvider
  ) {}

  update($event) {
     console.log('event', $event);
  }
}

そして最後に、なぜあなたのケースでビューが更新されるのかを答えますか? これは、テンプレートのイベント バインディングが原因です。

(click)="onClick($event)" 

これは、現在のコンポーネント ChangeDetectorRef.detectChanges() をトリガーするネイティブ イベントです。

于 2016-03-23T14:12:01.260 に答える