[英]ChangeDetectionStrategy.OnPush and Observable.subscribe in Angular 2
I'm trying to wrap my head around best practice when using Observables alongside ChangeDetectionStrategy.OnPush
. 在使用Observables和
ChangeDetectionStrategy.OnPush
时,我正试图围绕最佳实践。
The example demonstrates the common scenario of wanting to show some kind of loading message (or a simple spinner animation perhaps): 该示例演示了想要显示某种加载消息(或者可能是简单的微调器动画)的常见场景:
@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!';
}
});
}
}
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). 我或多或少了解
OnPush
对不变性的要求,至少对我而言,当谈到实际的模型数据(可能存在于某种商店中)时,它目前是有意义的。
So, I have two questions: 所以,我有两个问题:
'Success!'
'Success!'
trigger the change detector? loadingMessage
) be implemented when using ChangeDetectionStrategy.OnPush
? ChangeDetectionStrategy.OnPush
时,应如何实现轻量级内部组件状态(即loadingMessage
)? If there are multiple best practices, please point me in the right direction. 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): 我有两个来自Savkin的关于
onPush
(因为Angular.io文档似乎没有关于这个主题的任何信息):
The framework will check
OnPush
components only when their inputs change or components' templates emit events.只有在输入更改或组件模板发出事件时,框架才会检查
OnPush
组件。 -- ref- 参考
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.使用
OnPush
,Angular仅在任何输入属性更改时,触发事件时或者当observable触发事件时检查组件。 -- ref (in a comment reply to @vivainio)- 参考 (回复@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!
为什么不分配新的字符串值
Success!
trigger the change detector?触发变化检测器? As far as immutability is concerned, the value has changed, right?
就不变性而言,价值已发生变化,对吧?
OnPush
immutability is in reference to input properties, not normal instance properties. OnPush
不变性是指输入属性,而不是普通实例属性。 If loadingMessage
were an input property and the value changed, change detection would execute on the component. 如果
loadingMessage
是输入属性并且值已更改,则将在组件上执行更改检测。 (See @Vlado's answer for Plunker.) (参见@Vlado对Plunker的回答。)
How should lightweight internal component state (ie,
loadingMessage
) be implemented when usingChangeDetectionStrategy.OnPush
?使用
ChangeDetectionStrategy.OnPush
时,应如何实现轻量级内部组件状态(即loadingMessage
)? If there are multiple best practices, please point me in the right direction.如果有多种最佳实践,请指出正确的方向。
Here's what I know so far: 这是我目前所知道的:
OnPush
component (ie, the view will update). OnPush
组件上执行(即视图将更新)。 In your particular case, I was surprised that the view did not update. delay()
makes Angular look at it more like a setTimeout()
rather than an observable change. delay()
使Angular更像是setTimeout()
而不是可观察的更改。 setTimeout
s do not result in change detection execution on an OnPush
component. setTimeout
不会导致OnPush
组件上的更改检测执行。 In your example the Change Detector has completed its work 2 seconds before the value of loadingMessage
is changed. loadingMessage
的值更改之前2秒完成其工作。 Observable
. Observable
。 Ie, maybe it is more than just "an observable fires"... maybe it has to be a bound observable that fires. 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 . loadingMessage
(甚至更通用的state
属性)作为Observable
本身将允许您将模板绑定到其值(或多个异步值),请参阅此示例plnkr 。 | async
| async
| async
, as shown in the plnkr, and in this plnkr . | async
,如plnkr和此plnkr中所示 。 ChangeDetectorRef
into our component and call method markForCheck()
to cause change detection to execute on the OnPush
component and all ancestor components up to the root component. ChangeDetectorRef
到我们的组件和调用方法markForCheck()
引起的变化探测到上执行OnPush
组件和所有祖先组件升级到根零件。 If only view state is changed (ie, state that is local to the component and maybe its descendants), detectChanges()
can be used instead, which will not mark all ancestor components for change detection. detectChanges()
,而不会标记所有用于更改检测的祖先组件。 Plunker AFAIK, OnPush
is used when working directly with observables : 直接使用observable时使用AFAIK,
OnPush
:
//our root app component
import {Component, OnInit, ChangeDetectionStrategy} from 'angular2/core'
import {Observable} from 'rxjs/Observable';
import 'rxjs/Rx';
@Component({
selector: 'my-app',
template: `Are we loading?: {{ loadingMessage |async }}`,
changeDetection: ChangeDetectionStrategy.OnPush
})
export class App implements OnInit {
private loadingMessage;
constructor() { }
ngOnInit() {
this.loadingMessage = Observable.of(true)
.delay(2000)
}
}
With this ChangeDetectionStrategy.OnPush
you are telling your component to only listen for changes on it's input properties. 使用此
ChangeDetectionStrategy.OnPush
您告诉您的组件仅侦听其输入属性的更改。
I added loading component to your example just to show you how it works: http://plnkr.co/edit/k5tkmcLlzkwz4t5ifqFD?p=preview 我在您的示例中添加了加载组件,以向您展示它是如何工作的: http : //plnkr.co/edit/k5tkmcLlzkwz4t5ifqFD?p = preview
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.