“异步"管道不呈现流更新 [英] "async" pipe not rendering the stream updates
问题描述
尝试使用 async
管道通过 angular 2 组件中的流在窗口调整大小时呈现窗口大小:
尺寸:{{size$ |异步 |json}}</h2>
const windowSize$ = new BehaviorSubject(getWindowSize());Observable.fromEvent(window, 'resize').map(getWindowSize).subscribe(windowSize$);函数 getWindowSize() {返回 {高度:window.innerHeight,宽度:window.innerWidth};}@零件({选择器:'我的应用',提供者:[],模板:`<div><h2>尺寸:{{size$ |异步 |json}}</h2>
`,指令:[]})出口类应用{size$ = windowSize$.do(o => console.log('size:', o));构造函数(){}}
但是组件只呈现初始状态并忽略流更新.如果您打开控制台,在调整窗口大小时,您将看到来自同一流的更新.
无法理解我在这里遗漏了什么.
这是一个 plunker
事件处理程序在 Angular 区域之外运行,因此在事件触发时不会运行 Angular 更改检测.将事件处理程序放在您的组件中,然后它将与所有其他异步事件一起被猴子修补,因此 Angular 更改检测将在每个事件之后执行(并更新视图):
ngOnInit() {Observable.fromEvent(window, 'resize').map(getWindowSize).subscribe(windowSize$);}
<小时>评论中讨论的另一个选项是在更新视图模型时手动运行更改检测:>
import {Component, ChangeDetectorRef} from 'angular2/core'...出口类应用{size$ = windowSize$.do(o => {console.log('size:', o);//由于在 Angular 区域内未注册调整大小事件,//我们需要手动运行更改检测,以便视图更新this._cdr.detectChanges();});构造函数(私有_cdr:ChangeDetectorRef){}}
请注意,您可能想尝试运行一次 ApplicationRef.tick()
,例如在您的根组件中运行一次,这将对所有组件运行更改检测–而不是在每个组件中运行 ChangeDetectorRef.detectChanges()
.(并且您可能需要将 tick()
包装在 setTimeout()
方法中,以确保所有组件视图模型都已更新......我不确定当所有 do()
回调方法都将被执行时——即,如果它们都在 JavaScript VM 的一轮中运行,或者如果涉及多轮.)
Trying to render the window size on window resize through a stream in an angular 2 component utilizing an async
pipe:
<h2>Size: {{size$ | async | json}}</h2>
const windowSize$ = new BehaviorSubject(getWindowSize());
Observable.fromEvent(window, 'resize')
.map(getWindowSize)
.subscribe(windowSize$);
function getWindowSize() {
return {
height: window.innerHeight,
width: window.innerWidth
};
}
@Component({
selector: 'my-app',
providers: [],
template: `
<div>
<h2>Size: {{size$ | async | json}}</h2>
</div>
`,
directives: []
})
export class App {
size$ = windowSize$.do(o => console.log('size:', o));
constructor() { }
}
But the component only renders the initial state and ignores the stream updates. If you open the console, on window resize, you'll see the updates from that same stream.
Can't understand what i am missing here.
Here's a plunker
The event handler is running outside the Angular zone, so Angular change detection doesn't run when an event fires. Put the event handler inside your component and then it will get monkey-patched along with all of the other asynchronous events, hence Angular change detection will execute after each event (and update the view):
ngOnInit() {
Observable.fromEvent(window, 'resize')
.map(getWindowSize)
.subscribe(windowSize$);
}
Another option, discussed in the comments, is to manually run change detection when a view model is updated:
import {Component, ChangeDetectorRef} from 'angular2/core'
...
export class App {
size$ = windowSize$.do(o => {
console.log('size:', o);
// since the resize event was not registered while inside the Angular zone,
// we need to manually run change detection so that the view will update
this._cdr.detectChanges();
});
constructor(private _cdr: ChangeDetectorRef) {}
}
Note that you might instead want to try running ApplicationRef.tick()
once, say in your root component, which will run change detection on all of the components – rather than running ChangeDetectorRef.detectChanges()
in each component. (And you might need to wrap tick()
inside a setTimeout()
method, to ensure that all of the component view models were updated... I'm not sure when all of the do()
callback methods will be executed -- i.e., if they all run in one turn of the JavaScript VM, or if multiple turns are involved.)
这篇关于“异步"管道不呈现流更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!