1

我需要更新可观察对象的属性。我设法让它工作,但我真的不喜欢我是怎么做到的。

next(filter$: BehaviorSubject<GridCollectionFilter>, collection: GridCollectionModel<any>) {
  let filter = filter$.value;

  if (!filter.page) {
    filter.page = 1;
  }

  filter.page++;

  if (filter.page > collection.pageCount) {
    filter.page = collection.pageCount;
  }

  this.updateFilter(filter$);
}

first(filter$: BehaviorSubject<GridCollectionFilter>) {
  filter$.value.page = 1;
  this.updateFilter(filter$);
}

last(filter$: BehaviorSubject<GridCollectionFilter>, collection: GridCollectionModel<any>) {
  filter$.value.page = collection.pageCount;
  this.updateFilter(filter$);
}

updateFilter(filter$: BehaviorSubject<GridCollectionFilter>, filter?: GridCollectionFilter) {
  filter$.next(_.clone(filter || filter$.value));
}

在这种情况下,是否有更优雅的方式来更新filter$值对象?

filter$.next(_.clone(filter$.value))我真的不喜欢每次我只想通过代码更新被观察对象的一些属性时,将可观察对象的克隆喂给自己的想法。我_.clone()用来破坏引用(否则 rxjsdistinctUntilChanged()不会因为明显的原因触发)。

是否有某种 rxjs 扩展可以缩短我正在做的事情?我正在考虑一些filter$.commitValueChanges()内部会做的事情filter$.next(_.clone(filter$.value))

我对 observables 很陌生,所以我不确定我是否一开始就以完全错误的方式考虑这个问题。我知道当我想触发更改侦听器时,我应该提交新状态。我不确定您是否应该直接修改 filter$.value ?或者你通常应该有两个对象 - filter(过滤器)和filter$(可观察的过滤器),然后绝对不会filter$直接改变,而是在每次发生更改时简单filter.next()提交filter?但这似乎是多余的,因为我们现在有两个对象,我们正在通过应用程序更改一个对象,并且必须通过附加各种事件处理程序来手动处理,而所有这些只是为了能够更新另一个对象 -filter$. 这对我来说似乎太过分了。

谢谢。

4

3 回答 3

1

要从代码中删除 _clone(),您应该使用 distinctUntilKeyChanged()。它将检查对象中的任何键是否已更改。

DistinctUntilKeyChanged API

但更好的方法是:

filter$: BehaviorSubject<GridCollectionFilter>;
collection: GridCollectionModel<any>;
currentFilter: GridCollectionFilter; 

ngOnInit() {
  this.filter$.subscribe(filter => {
    this.currentFilter = filter;
    // Here for example invoke rest api with filter to change collection
  })
}

next() {
  if (!this.currentFilter.page) {
    this.currentFilter.page;
  }

  this.currentFilter.page++;

  if (this.currentFilter.page > this.collection.pageCount) {
    this.currentFilter.page = collection.pageCount;
  }

  this.filter$.next(this.currentFilter);
}

first() {
  this.currentFilter.page = 1;
  this.filter$.next(this.currentFilter);
}

last(filter$: BehaviorSubject<GridCollectionFilter>, collection: GridCollectionModel<any>) {
  this.currentFilter.page = collection.pageCount;
  this.filter$.next(this.currentFilter);
}
于 2017-11-24T12:07:05.217 回答
1

对于它的价值,我完全理解你的问题 - 因为我正在努力解决完全相同的问题。我遇到了许多 Angular 更改检测问题,因为我直接修改了主题的值。现在我只是 _.cloneDeep 值,对其进行修改,然后使用 .next() 将其反馈给主题。我也很欣赏主题的某种捷径来检测更改并发布新对象。目前,我还没有找到更好的解决方案。

于 2018-02-01T07:09:30.660 回答
0

如果您唯一的问题是您需要克隆对象,那么这些技巧之一可能会对您有所帮助:

  • 运算符默认比较distinctUntilChanged对象身份。但是,它需要一个可选compare功能,您可以使用它来实现您想要的任何比较登录。

    .distinctUntilChanged((a, b) => a.page === b.page)
    

    您还可以使用它来比较具有相同属性的两个不同实例

    .distinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b))
    
  • 如果您可以只创建浅拷贝,则可以使用以下其中一种:

    Object.assign({}, filter)
    

    或这个:

    { ...filter }
    

    这两个都是浅拷贝。

  • 如果您需要深层副本并且您不担心性能(似乎您的对象非常小),您可以使用JSON

    JSON.parse(JSON.stringify(filter))
    

    这样你就不需要任何 3rd 方库。

于 2017-11-24T13:23:17.393 回答