BehaviourSubject 不更新模板

问题描述 投票:0回答:2

我有一个 Angular 17 在线商店,但我遇到了 BehaviourSubject 未更新组件模板的问题。

客户选择产品,它们存储在 CartProduct 类中:id、name、num(该产品的元素数量)。然后一切都在 CartService 中管理,该服务有一个 BehaviourSubject 来存储它们:

@Injectable({
  providedIn: "root",
})
export class CartService {
  cartSubject: BehaviorSubject<CartProduct[]> = new BehaviorSubject<CartProduct[]>([]);

  get cart$(): Observable<CartProduct[]> {
    return this.cartSubject.asObservable();
  }
  
  ...
}

它还有一个“add”方法,用于接收 CartProduct 项目。此方法检查产品是否已在购物车中,如果产品已在列表中,它只会增加“num”计数器,如果不在,则会添加它:

add(cartProd: CartProduct) {
  const currentCart: CartProduct[] = this.cartSubject.getValue();
  const ind: number = currentCart.findIndex((x: CartProduct): boolean => x.id === cartProd.id);
  if (ind != -1) {
    currentCart[ind].num += cartProd.num;
  else {
  }
    currentCart.push(cartProd);
  }
  this.cartSubject.next(currentCart);
}

商店由三个组件组成(相当多,但这不是问题:P):HomeComponent、HeaderComponent 和 OneProductComponent。

HomeComponent 有一个标题,显示侧边栏,其中包含购物车中的元素列表:

import { Component, OnInit } from '@angular/core';
import { CartService } from './cart.service';

@Component({
  selector: 'app-header',
  template: `
    <ul>
      @for (product of cart; track product.id) {
      <li>
        {{ product.name }}
      </li>
      }
    </ul>
  `,
  styleUrls: ['./header.component.css'],
})
export class HeaderComponent implements OnInit {
  cart: CartProduct[] = [];

  constructor(private cartService: CartService) {}

  ngOnInit() {
    this.cartService.cart$.subscribe(() => {
      this.cart = this.cartService.cart$.value;
    });
  }
}

主页上有一个名为 OneProductComponent 的产品列表,基本上是一张图片、一个名称和一个将其添加到购物车的按钮。

import { Component } from '@angular/core';
import { CartService } from './cart.service';

@Component({
  selector: 'app-one-product',
  template: `
    <h2>{{ product.name }}</h2>
    <p>{{ product.price }} €</p>
    <button (click)="addProduct()">Add product</button>
  `,
  styleUrls: ['./one-product.component.css'],
})
export class OneProductComponent {
  constructor(private cartService: CartService) {}

  addProduct() {
    this.cartService.add({
      id: 1,
      name: 'Product 1',
      price: 10,
      num: 1,
    });
  }
}

问题是,当我单击组件上的按钮时,它不会反映在标题上。如果我导航到其他地方,标题会正确更新并显示购物车,但当我点击添加按钮时,它什么也不做。

我还在对服务的“添加”调用之后添加了此内容:

console.log(this.cartService.cartSubject.value);

我看到该产品已正确添加到购物车。但什么也没发生。我还尝试在购物车的添加方法上添加 EventEmitter 并在标题上订阅它:

CartService:

public productAdded$: EventEmitter<void>;

add(product: CartProduct) {
  ...
  this.cartSubject.next(currentCart);
  this.productAdded$.emit();
}

HeaderComponent:

constructor(cartService: CartService) {
  this.cartService.productAdded$.subscribe((): void => { console.log('product added'); });
}

也什么也没有发生。看起来它在加载时正确订阅并且显示了购物车,但是当我进行任何更改时,模板不会更新。

编辑:我在列表中的每个产品上添加了一个“x”以将其删除。我看到列表,我添加一些内容(列表未更新),我删除一些内容,列表更新删除元素并显示我添加的元素!看起来标题模板仅在对模板执行操作时才会刷新!

谢谢!

angular reflection shopping-cart
2个回答
0
投票

您需要使用 observable 订阅中的值,而不是 observable.value

// Incorrect
    this.cartService.cart$.subscribe(() => {
      this.cart = this.cartService.cart$.value;
    });

// Correct
    this.cartService.cart$.subscribe(value => {
      this.cart = value;
    });

0
投票

找到了!!问题是我在启动时将 CartService 作为全局提供程序加载,但我在 HeaderComponent 和 OneProductComponent 上也有一个“providers”数组。我刚刚从组件中删除了该数组...现在它可以完美运行:)

感谢bmtheo的帮助!

© www.soinside.com 2019 - 2024. All rights reserved.