无论分离设置如何,更改检测似乎都发生在单击事件上

Change detection appears to occur on click event regardless of detached setting

这可能是我自己对 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 属性,无论值是否已更改,视图都会在单击时更新。

我希望这能帮助你理解它:)

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 通过区域 api 发现任何异步事件更改时,区域通知 angular 在该上下文中发生了异步事件并将其传播到 angular 更改detection api 在实际视图和组件之间进行检查,在下面的示例中我们可以看到,由于更改检测行为未更改 angular 不断更新视图:

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 将仅在组件初始化过程中触发一次更改检测,在这种情况下,您必须手动触发更改以更新视图本例通过事件绑定完成:

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()

无论 ChangeDetectionStrategy 设置如何,Angular 都会在

时检查组件的更改
  • 组件触发事件
  • 一个 observable 触发了一个事件,并且异步管道在具有该 observable 的视图中使用

想法是...如果组件触发了一个事件,或者绑定的可观察值发生了变化,很可能您想更新它的视图。