ChangeDetectionStrategy.OnPush何时实际运行变更检测?

时间:2018-01-02 22:33:38

标签: javascript angular typescript

我正在构建一个包含许多组件的Angular 4应用,其中ChangeDetectionStrategyOnPush。虽然the Angular Documentation on the matter没有太多信息,但各种消息来源表示OnPush个组件仅在其@Input更改时更新(新对象或基元)。

但是,OnPush组件内的各种事件似乎也会触发变更检测。但是,我注意到其他人没有触发变化检测。

ChangeDetectionStrategy.OnPush关于组件内事件的具体规则是什么?

2 个答案:

答案 0 :(得分:1)

来自Change Detection Strategy: OnPush

  

这将告知Angular我们的组件仅依赖于它的输入,并且传递给它的任何对象都应该被认为是不可变的。

它继续表明属性更改不会触发更改检测(被认为是不可变的),但对对象本身的更改会触发更改检测。

所以看起来关键标准是不变性。模板上引用的对象的更改触发器为

  • 对象 引用 代码更改(父级更改输入值 在子级内更改) 触发更改检测。
  • 对象 属性 外部 更改 组件 触发更改检测。
  • 对象 属性 更改 组件 < / strong>触发更改检测。

我没有测试过一个可观察的变化,但是在别处作为触发器给出了变化。 (可观察的发射会更改对象引用,而不是它的属性)。

使用角度版 5.2.0-beta.1

进行测试

扩展RangleIO示例

帖子顶部引用的RangleIO页面有一个Plunker,它说明通过Input()参数传递给组件的对象被认为是不可变的。子组件的更改检测器不会响应输入对象属性的更改。

但是,在复制了 中的更改按钮后,可以看到在组件自己的代码中调用的对象属性更改将改变它的视图。

以下是代码Plunker

<强> movie.component.ts

@Component({
  selector: 'app-movie',
  styles: ['div {border: 1px solid black}'],
  template: `
    <div>
      <h3>{{ title }}</h3>
      <p>
        <label>Actor:</label>
        <span>{{actor.firstName}} {{actor.lastName}}</span>
      </p>
      <button type="button" (click)="changeActorProperties()">
        Inside Movie Component - Change Actor Properties (will change view)
      </button>
      <button type="button" (click)="changeActorObject()">
        Inside Movie Component - Change Actor Object (will change view)
      </button>
    </div>`,
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class MovieComponent {
  @Input() title: string;
  @Input() actor: Actor;

  changeActorProperties(): void {
    this.actor.firstName = 'Nicholas';
    this.actor.lastName = 'Cage';
  }

  changeActorObject(): void {
    this.actor = new Actor('Bruce', 'Willis');
  }
}

<强> app.component.ts

@Component({
  selector: 'app-root',
  template: `
    <h1>MovieApp</h1>
    <p>{{ slogan }}</p>
    <button type="button" (click)="changeActorProperties()">
      Outside Movie Component - Change Actor Properties (will not change Movie view)
    </button>
    <button type="button" (click)="changeActorObject()">
      Outside Movie Component - Change Actor Object (will change Movie view)
    </button>
    <app-movie [title]="title" [actor]="actor"></app-movie>`
})
export class AppComponent {
  slogan = 'Just movie information';
  title = 'Terminator 1';
  actor = new Actor('Arnold', 'Schwarzenegger');

  changeActorProperties(): void {
    this.actor.firstName = 'Nicholas';
    this.actor.lastName = 'Cage';
  }

  changeActorObject(): void {
    this.actor = new Actor('Bruce', 'Willis');
  }
}

答案 1 :(得分:1)

This blog post的{p> Angular University包含有关使用ChangeDetectionStrategy.OnPush时触发更改检测的事件的若干说明:

  

OnPush变化检测器在其他几个中被触发   除了组件Input()引用的更改之外的其他情况,它也是   被触发例如:

     
      
  • 如果组件事件处理程序被触发
  •   
  • 如果通过异步管道链接到模板的observable发出新值
  •   

他们添加了以下建议:

  

因此,如果我们记得尽可能多地订阅任何观察者   使用模板级别的异步管道,我们得到了几个   优点:

     
      
  • 我们将使用OnPush
  • 来减少更改检测问题   
  • 我们会的   从默认的更改检测切换更容易   如果我们需要
  • ,稍后会对OnPush采取策略   
  • 不可变数据和@Input()   参考比较不是实现高性能的唯一方法   使用OnPush的UI:反应式方法也是使用OnPush的选项   有效
  •   

在问题&#34; {Angular 2&#34;在Victor,Viktor Savkin解释说:

  

使用OnPush探测器时,框架将检查OnPush   组件在其任何输入属性发生更改时,触发时   事件,或当一个观察者发射事件时。