BehaviorSubject 不保留数组和重复项

BehaivorSubject not keep array and duplicate

我有一个服务和一个组件,当我添加一个值时,它会保留在数组中,但是当我添加其他值时,我的第一个值会将值更改为第二个

服务

 export class PrepayService {
  private _carts: BehaviorSubject<ShoppingCart[]>; 
  carts : Observable<ShoppingCart[]>
  dataStore :{
    carts: ShoppingCart[]
  };
  constructor() { 
    this.dataStore = { carts: []};
    this._carts = <BehaviorSubject<ShoppingCart[]>>new BehaviorSubject([]);
    this.carts = this._carts.asObservable();
  }

  addData(dataObj:ShoppingCart) {
    this.dataStore.carts.push(dataObj);
    this._carts.next(Object.assign({}, this.dataStore).carts);
  }
}

组件

export class TableQuoteComponent implements OnInit {

  @Input() quote: QuoteSingle = {};
  cart: ShoppingCart;
  serviceSelected : string;

  constructor(private cartService: PrepayService) { }

  ngOnInit() {
  }
  onSubmitAdd(){
    this.cart = {};
    this.cart = this.quote;
    this.cartService.addData(this.cart);

  }
}

第二个组件

export class PrePayComponent implements OnInit {
  carts: ShoppingCart[];
  constructor(private cartService: PrepayService) { }

  ngOnInit() {
    this.cartService.carts.subscribe(carts => this.carts = carts);
    console.log(this.carts);
  }

}

数组值 enter image description here enter image description here

我认为这是一个参考值。 Object.assign({}, this.dataStore) 将按值复制而不是按属性的第一个深度的引用。所以购物车不会按值复制,它会按引用复制。所以我假设这里发生的事情是您添加一个新的 'Quote' 并添加到购物车中,该购物车被添加到主题流中。但是,当您重新分配 this.quote 时,您也会更改 dataStore 中的值,从而更改主题,因为它是通过引用复制的。

要解决此问题,请像这样修改服务的 addData() 方法:

this.dataStore.carts.push(deepCopy(dataObj); // Here we need to deep copy the ShoppingCart. I don't know what your structure looks like. JSON.parse(JSON.stringify(dataObj)) will work for a cheap and easy deep copy.
this._carts.next(deepCopy(this.dataStore.carts)); // Deep copy the carts object here.

抱歉,我不是很擅长解释,但这基本上是您遇到的引用复制问题。经常发生。 其他人可能有更好的解决方案。

在您的 TableQuote 组件中,您在 cartService.addData 方法中传递了 cart 属性 的引用,当您第二次添加时,您更改了 cart 属性 改变第一个元素。你应该传递 cart 属性 的副本,如下所示

this.cartService.addData({...this.cart});

this.cartService.addData(Object.assign({},this.cart));

在 javascript 或打字稿中,对象和数组是可变的,这意味着当您传递这些变量时,您实际上传递的是引用,而不仅仅是它的值。