首页 文章

如何从代码中更新Observable / BehaviorSubject?

提问于
浏览
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() 来打破引用(否则rxjs distinctUntilChanged() 由于显而易见的原因不会触发) .

是否存在某种rxjs扩展,它可以缩短我在 filter$.commitValueChanges() 内部做_1182764_的思路 .

我'm pretty new to observables so I'我不确定当我想要触发更改侦听器时,我是否应该提交新状态 . 我有什么想直接修改过滤器$ .value的?或者你通常应该有两个对象 - filter (过滤器)和 filter$ (可观察过滤器)然后绝对不会直接改变 filter$ 但只是在每次 filter 发生变化时提交 filter.next() ?但那似乎是多余的,因为我们现在有两个对象,一个我们正在通过应用程序进行更改,并且必须通过附加各种事件处理程序手动处理,以及只能更新另一个 - filter$ . 这对我来说似乎过分和苛刻 .

日Thnx .

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);
    }
    
  • 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))
    

    这样您就不需要任何第三方库 .

  • 0

    对于它的 Value ,我完全理解你的问题 - 因为我正在努力解决同样的问题 . 我碰到了许多角度变化检测问题,因为我直接修改了主题的 Value . 现在我只是_.cloneDeep值,修改它然后用.next()将它反馈回主题 . 我也会欣赏主题检测更改和发布新对象的某种快捷方式 . 目前,我还没有找到更好的解决方案 .

相关问题