“异步"管道不呈现流更新 [英] "async" pipe not rendering the stream updates

查看:14
本文介绍了“异步"管道不呈现流更新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

尝试使用 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$);}

Plunker

<小时>

评论中讨论的另一个选项是在更新视图模型时手动运行更改检测:>

import {Component, ChangeDetectorRef} from 'angular2/core'...出口类应用{size$ = windowSize$.do(o => {console.log('size:', o);//由于在 Angular 区域内未注册调整大小事件,//我们需要手动运行更改检测,以便视图更新this._cdr.detectChanges();});构造函数(私有_cdr:ChangeDetectorRef){}}

Plunker

请注意,您可能想尝试运行一次 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$);
}

Plunker


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) {}
}

Plunker

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屋!

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