【问题标题】:How to subscribe on variable changes?如何订阅变量更改?
【发布时间】:2023-03-26 15:26:01
【问题描述】:

我已经声明了以下变量:

public filter: IFilterWeekScheduleClassShort = {};

如何订阅更改(监听对象过滤器)?

我试过了:

private filter: IFilterWeekScheduleClassShort = {};
private filterChanges: BehaviorSubject<IFilterWeekScheduleClassShort> = new BehaviorSubject(this.filter);

this.filterChanges.subscribe((model) => {
    console.log(model);
});

没事吧?

我的最终代码:

public _filter: IFilterWeekScheduleClassShort = {};
private filterChanges: BehaviorSubject<IFilterWeekScheduleClassShort> = new BehaviorSubject(this._filter);

  this.filter = {a: 1, b: 2}

  set filter(value: any) {
    this._filter = value;
    this.filterChanges.next(this._filter);
  }

  get filter() {
    return this.filterChanges.asObservable();
  }

订阅:

this.filter.subscribe(model => {
   console.log(model);
});

我对表单所做的更改:

[(ngModel)]="_filter.teacherId"

【问题讨论】:

  • 你的最终目标是什么?可能有比订阅更改事件更好的方法(这通常是一项昂贵的操作,因为它可能会被多次调用)
  • 目标是检测filter 对象中的任何变化并决定接下来要做什么
  • Subject/BehaviorSubject 允许您发布和收听更改。您可以this.filterChanges.next(data) 发布任何更改,this.filterChanges.subscribe((data)=&gt;this.filter = data) 监听任何更改

标签: angular typescript rxjs


【解决方案1】:

我认为你想要得到的关闭是使用scan()

const filterChanges$ = new Subject()
const defaultFilter = {}

const filter$ = filterChanges$
  .pipe(
    scan((acc, mergeFilter) => {
      return {
        ...acc,
        ...mergeFilter,
      }
    }, defaultFilter)
  )

filter$.subscribe(console.log);

filterChanges$.next({ name: 'abc' })
filterChanges$.next({ num: 42 })
filterChanges$.next({ name: 'xyz' })

现场演示:https://stackblitz.com/edit/rxjs6-demo-ngqkzv?file=index.ts

这将输出:

{name: "abc"}
{name: "abc", num: 42}
{name: "xyz", num: 42}

前段时间,我为 window.Proxy 做了一个小包装器,名为 rxjs-observable-object,它可以让你包装任何对象,然后监听它的变化 (https://github.com/martinsik/rxjs-ds#object):

import { map } from 'rxjs/operators';
import { ObservableObject } from 'rxjs-observable-object';

const defaultFilter = {}
const { proxy, events } = new ObservableObject(defaultFilter);

const filter$ = events.onSet
  .pipe(
    map(({ target }) => target)
  )

filter$.subscribe(console.log);

proxy['name'] = 'abc';
proxy['num'] = 42;
proxy['name'] = 'xyz';

现场演示:https://stackblitz.com/edit/rxjs6-demo-hojjkk?file=index.ts

不过,rxjs-observable-object 现在有点过时了,还需要安装 rxjs-comapt 软件包。

两个示例的输出相同。

【讨论】:

    【解决方案2】:

    做一个二传手

    private _filter: IFilterWeekScheduleClassShort = {};
    set filter(value) {
      this.doSomethingOnVariableChange(value);
      this._filter = value;
    }
    

    现在可以这样使用了

    this.filter = 'x';
    

    您的函数doSomethingOnVariableChange 将被'x' 调用。

    有一个可观察的:

    private _filter: IFilterWeekScheduleClassShort = {};
    private _filter$ = new BehaviorSubject(this._filter);
    set filter(value) {
      this._filter = value;
      this._filter$.next(this._filter);
    }
    get filter() {
      return this._filter$.asObservable();
    }
    

    【讨论】:

    • 喜欢一种方式,但我想用Observer
    • 看起来不漂亮,可以吗?也许我选择了错误且不合逻辑的方式?
    • 要显示更改,请在set 中执行,因为您希望在设置值时显示更改。当你订阅时,它在this.filterthis.filter.subscribe(value =&gt; console.log(value))
    • 不。我的意思是,你可以,但吸气剂是专门为此而设计的。
    • 你确定你写的是this._filter$.next(this._filter);,而不是this._filter$.next(this._filter$);
    猜你喜欢
    • 2018-02-21
    • 2016-06-03
    • 2020-12-06
    • 2019-04-27
    • 2016-12-03
    • 1970-01-01
    • 2018-12-13
    • 2022-07-01
    • 2021-11-25
    相关资源
    最近更新 更多