如何使 class 可观察?

How to make class Observable?

我有 class 具有属性:

export class Model {
   public id: number;
   public name: string;
}

如何使这个 class 可观察,以监听 m 属性的变化。

我需要这样的东西:

let m = new Model();
m.id = 10;

监听变化:

m.pipe(map() => m.id);
let m = new Model();
m.id = 10;


const model$ = of(m);
model$.pipe(map()=> m.id);

您可以为您的 class 属性添加 getter 和 setter,在内部添加发射器,然后在 class 外部添加侦听器,这将侦听被发射的发射器

这是一个简单的例子。

https://stackblitz.com/edit/angular-ivy-kc9e4q

import { Component, OnInit, VERSION } from '@angular/core';
import {BehaviorSubject} from 'rxjs';


@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit {
model: Model;

  ngOnInit() {
    this.model.id$.subscribe(newid => {
      // do something.
    });
  }
}
export class Model {
  // @ts-ignore
  private readonly _id = new BehaviorSubject<number>();
  readonly id$ = this._id.asObservable();
  // @ts-ignore
  private readonly _name = new BehaviorSubject<string>();
  readonly name$ = this._name.asObservable();

  get id(): number {
    return this._id.getValue();
  }

  set id(val) {
    this._id.next(val);
  }

  get name(): number {
    return this._name.getValue();
  }

  set name(val) {
    this._name.next(val);
  }
}

我的方法是将功能注入构造函数。我会避免在 class 中声明主题,因为它们很难自动整理。

您可以注入主题,但更简单的替代方法是注入回调。

在下面的测试 class 中,我允许每个 属性 注入一个回调。如果值已更改,则会在 属性 setter 中调用相关回调。

export class MyClass {
  private _id: number;  
  private _name: string;

  constructor(private callback?: {
    id?: () => void,
    name?: () => void
  }) {}

  get id(): number { 
    return this._id;
  }

  set id(value: number) {
    if (value === this._id) {
      return;
    }

    this._id = value;

    if (this.callback && this.callback.id) {
      this.callback.id();
    }
  }

  get name(): string {
    return this._name;
  }

  set name(value: string) {
    if (value === this._name) {
      return;
    }

    this._name = value;

    if (this.callback && this.callback.name) {
      this.callback.name();
    }
  }
}

然后从其他地方使用它就相当简单了。

myClass: MyClass = new MyClass({
  id: () => this.onIdChange()
});

ngOnInit() {
  this.myClass.id = 10;   
  this.myClass.name = 'Default' 
}

private onIdChange() {
  console.log(`id changed to ${this.myClass.id}`);
}

如果您确实需要,可以很简单地更改它以使用主题。然后调用代码将负责在适当的时候整理主题。

演示:https://stackblitz.com/edit/angular-ivy-hgxkc3