Angular 2中的ChangeDetectionStrategy.OnPush和Observable.subscribe [英] ChangeDetectionStrategy.OnPush and Observable.subscribe in Angular 2

查看:148
本文介绍了Angular 2中的ChangeDetectionStrategy.OnPush和Observable.subscribe的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在使用Observables和 ChangeDetectionStrategy.OnPush 时,我正试图绕过最佳实践。

I'm trying to wrap my head around best practice when using Observables alongside ChangeDetectionStrategy.OnPush.

该示例演示了想要显示某种加载消息(或者可能是简单的微调器动画)的常见场景:

The example demonstrates the common scenario of wanting to show some kind of loading message (or a simple spinner animation perhaps):

Plnkr在这里

@Component({
  selector: 'my-app',
  template: `Are we loading?: {{loadingMessage}}`,

  // Obviously "Default" will notice the change in `loadingMessage`...
  // changeDetection: ChangeDetectionStrategy.Default

  // But what is best practice when using OnPush?
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class App implements OnInit {

  private loadingMessage = "Wait for it...";

  constructor() {

  }

  ngOnInit() {

    // Pretend we're loading data from a service.
    // This component is only interested in the call's success
    Observable.of(true)
      .delay(2000)
      .subscribe(success => {

        if(success){
          console.log('Pretend loading: success!');

          // OnPush won't detect this change
          this.loadingMessage = 'Success!';
        }

      });

  }
}

我或多或少了解要求对于 OnPush 的不变性,至少对我来说,当谈到实际模型数据(可能存在于某种商店中)时,它目前是有意义的。

I more or less understand the requirement for immutability with OnPush and, to me at least, it currently makes sense when talking about actual model data (likely held in some kind of store).

所以,我有两个问题:


  1. 为什么不进行分配新字符串值'成功!'触发更改检测器?就不变性而言,价值已发生变化,对吗?

  2. 轻量级内部组件状态(即 loadingMessage )应该如何使用 ChangeDetectionStrategy.OnPush 时实现?如果有多种最佳做法,请指出正确的方向。

  1. Why doesn't the assignment of the new string value 'Success!' trigger the change detector? As far as immutability is concerned, the value has changed, right?
  2. How should lightweight internal component state (ie. loadingMessage) be implemented when using ChangeDetectionStrategy.OnPush? If there are multiple best practices, please point me in the right direction.


推荐答案

好问题。我有两个来自Savkin的引用关于 onPush (因为Angular.io文档似乎没有关于这个主题的任何信息):

Good question. I have two quotes from Savkin about onPush (since the Angular.io docs don't seem to have any info on this topic yet):


只有当输入更改或组件模板发出事件时,框架才会检查 OnPush 组件。 - ref

使用时 OnPush ,Angular只会在任何输入属性发生变化,触发事件或者observable触发事件时检查组件。 - ref (在回复@vivainio的评论中)

When using OnPush, Angular will only check the component when any of its input properties changes, when it fires an event, or when an observable fires an event. -- ref (in a comment reply to @vivainio)

第二个引用似乎更完整。 (太糟糕了,它被埋没在评论中!)

The second quote seems more complete. (Too bad it was buried in a comment!)


为什么不分配新的字符串值成功!触发
变化检测器?就不变性而言,价值已发生变化,对吗?

Why doesn't the assignment of the new string value Success! trigger the change detector? As far as immutability is concerned, the value has changed, right?

OnPush immutability是指输入属性,而不是普通的实例属性。如果 loadingMessage 是输入属性并且值已更改,则将在组件上执行更改检测。 (请参阅@Vlado对Plunker的回答。)

OnPush immutability is in reference to input properties, not normal instance properties. If loadingMessage were an input property and the value changed, change detection would execute on the component. (See @Vlado's answer for Plunker.)


轻量级内部组件状态应该如何(即 loadingMessage )在使用 ChangeDetectionStrategy.OnPush 时实现?如果有多种最佳做法,请指出正确的方向。

How should lightweight internal component state (i.e., loadingMessage) be implemented when using ChangeDetectionStrategy.OnPush? If there are multiple best practices, please point me in the right direction.

这是我目前所知道的:


  • 如果我们将内部状态更改为处理事件或可观察触发的一部分,则更改检测将在 OnPush <上执行/ code>组件(即视图将更新)。在您的特定情况下,我很惊讶该视图没有更新。以下是两个猜测,为什么不:


    • 添加 delay()让Angular看一下比如 setTimeout()而不是可观察到的变化。 setTimeout s不会导致在 OnPush 组件上执行更改检测。在您的示例中,更改检测器已在 loadingMessage 的值更改前2秒完成其工作。

    • 喜欢@Sasxa显示在他的回答,你必须在模板中有一个绑定到 Observable 。也许它不仅仅是一个可观察到的火焰......也许它必须是一个强烈的绑定可观察物。在这种情况下,创建 loadingMessage (或甚至更通用的属性)作为 Observable 本身允许您将模板绑定到其值(或多个异步值),请参阅此示例plnkr
      更新2016-04-28:看来绑定必须包含 | async ,如plnkr和此plnkr 所示。

    • If we change the internal state as part of handling an event, or part of an observable firing, change detection executes on the OnPush component (i.e., the view will update). In your particular case, I was surprised that the view did not update. Here are two guesses as to why not:
      • Adding delay() makes Angular look at it more like a setTimeout() rather than an observable change. setTimeouts do not result in change detection execution on an OnPush component. In your example the Change Detector has completed its work 2 seconds before the value of loadingMessage is changed.
      • Like @Sasxa shows in his answer, you have to have a binding in the template to the Observable. I.e., maybe it is more than just "an observable fires"... maybe it has to be a bound observable that fires. In which case, creating loadingMessage (or even a more generic state property) as an Observable itself will allow you to bind your template to its value (or multiple async values), see this example plnkr.
        Update 2016-04-28: it appears the binding must include | async, as shown in the plnkr, and in this plnkr.

      这篇关于Angular 2中的ChangeDetectionStrategy.OnPush和Observable.subscribe的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆