为什么可观察结果不会改变而数组 push/splice

Why observable result won't change while array push/splice

我有这样的服务:

export class ArrService {
  private arr: any[] = [1,2,3];

  constructor() {}

  setValue(index: number, value: number): void {
    this.arr[index]= value;
  }

  addItem(value: any): void {
    this.arr.push(element);
  }

  removeItem(index: number): void {
    this.arr.splice(index, 1);
  }

  getItems(): Observable<any> {
    return of(this.arr);
  }
}

并且为了进一步的目的,我订阅了组件中可观察到的 getItems():

this.arrService.getItems().subscribe(res => {
  this._arr = res;
});

所有的动作都是直接调用ArrService中的函数。 当我调用 setValue() 时,ArrService 中的源数组和组件中的本地数组都发生了变化。 而且我记录了 obseravble 在更改时没有再次发出,所以我猜 observables 应该通过引用传递。

但是当我调用addItem() 和removeItem() 时,源改变了,而本地没有。 那么 observable 不是通过引用传递的吗?或者我误解了 obseravble 的工作原理?

我知道主题或行为主题可以完成我的服务。 但我想知道在这种情况下 observable 是如何发挥作用的,为什么有些动作会被执行而有些不会。

主题是一种可观察对象。因此,它是一个流。您可以向流中添加一个项目(例如一个数字),该项目将广播给流的任何观察者。

private arr = new Subject<any[]>();

或者如果您需要默认值:

private arr = new BehaviorSubject<any[]>([1,2,3]);

以这种方式在 setValue 中引发事件:

  setValue(index: number, value: number): void {
    this.arr.next(value);
  }

以这种方式更改 getItems:

  getItems(): Observable<any> {
    return this.arr.asObservable();
  }

最终结果:

@Injectable()
export class ArrService {
  private arr = new BehaviorSubject<any[]>([1,2,3]);

  constructor() {}

  setValue(index: number, value: number): void {
    let tst = this.arr.value;
    tst.push(value);
    this.arr.next(tst);
  }


  getItems(): Observable<any> {
    // return of(this.arr);
    return this.arr.asObservable();
  }
}

尝试Subject

export class ArrService {
  private arr: any[] = [1,2,3];
  private arr$ = new Subject();

  constructor() {}

  setValue(index: number, value: number): void {
    this.arr[index]= value;
    this.arr$.next(this.arr);
  }

  addItem(value: any): void {
    this.arr.push(element);
    this.arr$.next(this.arr);
  }

  removeItem(index: number): void {
    this.arr.splice(index, 1);
    this.arr$.next(this.arr);
  }

  getItems(): Observable<any> {
    return this.arr$.asObservable();
  }
}

如果要保留最后发出的值,请使用 BehaviorSubject(在使用 .next() 发出值后进行订阅的情况下很有用)


当您使用数组时,始终存在与监视其中所做的任何更改相关的问题。你会在其他 angular 地方遇到类似的行为,如果你向数组插入任何新值,“ngOnChange”甚至“zone.js”都不会检测到值的任何变化。 .