如何比较Observables:NGRX和使用Observable的Observables进行有效的Angular 4渲染

时间:2017-11-22 15:56:50

标签: javascript angular rxjs rxjs5 ngrx

概览

关注容器 - >组件模式并使用ngrx来集中我们的应用程序状态。

应用程序结构如下:

Container
   Child_Comp_1
      Child_Comp_2
         Child_Comp_3

最初,在Container中订阅了一个可观察的数据,然后将相关数据作为输入传递给子组件。比如

Observable<
 {
   data,
   collection: []
 }> 

但是,任何更新都会触发ngrx选择器并导致AngularJS重新呈现组件链。

我们开始提供可观察的可观察物,

Observable< 
 {
  data: Observable<data>
  collection: Observable<Observable<Item>[]>
 }>

我们现在可以使用诸如DistinctUntilChanged(谓词)之类的RxJs函数来指定实际触发组件中的订阅的时间。

并使用ChangeDetection.markForCheck()来限制重新渲染的位置

问题&amp;问题

有两个问题

  1. 使用我们的Observable数组 - 什么是比较两个Observable的值以查看是否有任何更改的最佳方法
  2. 例如:
    collection.distinctUntilChanged((a, b) => ?? compare values of a b ??)

    1. 使用Observable的Observable,以便不同的子组件可以定义触发订阅的标准,从而使其他区域更加困难。有更好的方法吗?
    2. 示例:

      Child Comp

        collection
         .distinctUntilChanged((a, b) => a.length === b.length)
         .subscribe(items => ....)  // only fired if length changed
      

1 个答案:

答案 0 :(得分:0)

我这样做的方法是只发送一个值并从中派生出可观察量,而不是发送可观察量的可观察量。

private subj: Subject<{data:any, collection: any[]}> = new Subject<{data:any, collection: any[]}>();
src$: Observable<{data:any, collection: any[]}> = this.subj.distinctUntilChanged();
data$: Observable<any> = this.src$.pluck('data').distinctUntilChanged();
collection$: Observable<any[]> = this.src$.pluck('collection').distinctUntilChanged();

this.src$.subscribe(v => console.log(v));
this.data$.subscribe(v => console.log(v));
this.collection$.subscribe(v => console.log(v));

distinctUntilChanged的默认行为是对象引用(或原始)比较。因此,关键是要强制实现对象不变性,只改变需要更新的对象,并在执行时重新引用它们。

const obj = { data: {}, collection: []; };
this.subj.next(obj); // all subscribers trigger
const dataUpdate = Object.assign({}, obj, {data: { prop1:'new Val' }}); // change only the data property, collection untouched
this.subj.next(dataUpdate); //src and data trigger
const collUpdate = Object.assign({}, dataUpdate, { collection: [1] }); // change only collection property, data untouched
this.subj.next(collUpdate); //src and coll fire
const collUpdate2 = Object.assign({}, collUpdate, { collection: collUpdate.collection.concat([2]) }); // add to existing collection
 this.subj.next(collUpdate2); //src and coll fire
const collUpdate3 = Object.assign({}, collUpdate2, { collection: collUpdate2.collection.splice(0,1) }); //reomve from existing collection
 this.subj.next(collUpdate3); //src and coll fire

这是一般模式,获取您的最后一个值,以及您的更新,并以这样的方式应用更新,即它只更新应更新的部分,包括它的所有祖先。这就是ngrx真正做的事情,它使用扫描操作符,它获取您累积的vallue(最后一个值)和您的新操作(您的更新)并以这样的方式应用更改,即只需要更新的部分得到更新(减速机)。 ngrx的“select”函数也会处理所有distinctUntilChanged()内容,因此您无需担心它。