带有 ChangeDetectionStrategy.OnPush 和异步管道的 Angular 2 Observable 不起作用

Posted

技术标签:

【中文标题】带有 ChangeDetectionStrategy.OnPush 和异步管道的 Angular 2 Observable 不起作用【英文标题】:Angular 2 Observable with ChangeDetectionStrategy.OnPush and async pipe are not working 【发布时间】:2016-11-04 19:58:31 【问题描述】:

我使用 observable 将列表从服务返回到我的组件,在我的组件中我使用 ChangeDetectionStrategy.OnPush,在模板中我使用异步管道,希望这会带来一些性能优势,因为没有执行更改检测一直都有,但只有在有新内容可用时。

以下是我的服务:

import  Injectable, Inject, EventEmitter  from '@angular/core';
import  Observable  from 'rxjs/Observable';
import  Subject  from 'rxjs/Subject';

@Injectable()
export class ListService 

    public _list$: Subject<any[]>;

    private list: any[] = [];

    constructor() 
        this._list$ = <Subject<any>>new Subject();
    

    get list$() 
        return this._list$.asObservable();
    

    loadList() 
        //if this.list is populated through an http call the view is updated, 
        //if its a static list like below, it doesn't trigger view update.
        //this.list = ['Red', 'Green', 'Yellow', 'Blue'];
        this._list$.next(this.list);
    

在我的组件中我有:

import  Component, ChangeDetectionStrategy  from '@angular/core';
import  Observable  from 'rxjs/Observable';

@Component(
    templateUrl: `
<ul>
        <li *ngFor="let item of (list$ | async);">
            item
        </li>
    </ul>
`,
    changeDetection: ChangeDetectionStrategy.OnPush
)
export class ListComponent 

    public list$: Observable<any[]>;

    constructor(
        private _ls: ListService
    ) 

    ngOnInit() 
        this.list$ = this._ls.list$;
        this._ls.loadList();
    

如果 loadList 内容通过 http 调用获取列表内容,则视图会更新,如果列表内容是静态的,则视图不会更新。

如果我将列表更新包装在 setTimeout 中,它会触发视图更新

setTimeout(() => 
    this._list$.next(this.list);
, 1);

我刚开始探索 Observables,谁能指导一下上面的代码有什么问题?

【问题讨论】:

【参考方案1】:

只需将代码从ngOnInit() 移至构造函数即可。 Angular 在调用 ngOnInit() 之前尝试解析绑定(订阅 observable)并失败,因为 thod._list$null 并且稍后不会尝试,因为它无法识别更改。

【讨论】:

非常感谢 Günter 的回复。但这似乎并不能解决问题。如果服务中的 loadList 方法进行 http 调用,或者将其包装在 setTimeout(() => this._list$.next(this.list); , 1);它有效,否则无效。 setTimeout() 导致更改检测运行。您是否真的尝试将代码移动到构造函数?您可以尝试将第一行移至构造函数。 是的,我移动了这一行 this.list$ = this._ls.list$;到构造函数。 我也尝试添加 this.list$.subscribe((data) => console.log(data); );到 ngOnInit() 以确认数据是否实际上是从服务发送的,并且日志显示该数据实际上正在被检索但视图没有更新。 你使用的是哪个 Angular2 版本?

以上是关于带有 ChangeDetectionStrategy.OnPush 和异步管道的 Angular 2 Observable 不起作用的主要内容,如果未能解决你的问题,请参考以下文章

使用带有 uuencode 的“sendmail”发送邮件,并带有主题

带有和不带有聚合的 sql 查询

如何翻转正面带有标签而背面带有另一个标签的视图 - 参见图片

CakePHP 如何处理带有/不带有 'id' 字段的 HABTM 表?

带有滚动的 Div 和带有绝对位置的内容

带有 RecyclerView 的 DialogFragment 比带有 Recyclerview 的 Fragment 慢