【问题标题】:Communication between the components in AngularAngular中组件之间的通信
【发布时间】:2019-12-26 13:45:52
【问题描述】:

我是 Angular 新手。

这是我的测试应用程序。

https://stackblitz.com/github/tsingh38/lastrada(请点击披萨) 我有 2 个组件 Pizza 和 Cart。

比萨 → PizzaunitComponent 购物车→ CartComponent 一旦用户选择了列出的比萨饼之一。单击购物车组件的按钮会发出更改。我在哪里显示所选项目。

  onSubmit() {
    this.orderedPizza.id = this.pizza.pizzaId;
    this.orderedPizza.pizza=this.pizza;
    this.orderedPizza.name = this.pizza.pizzaName;
    this.orderedPizza.quantity = this.selectedQuantity;
    this.orderedPizza.size = this.selectedSize;
    this.orderedPizza.listOfAdditions = this.listOfCheckedPizzaAdditions;
    this.orderedPizza.totalPrice = this.priceOnButton;
    this.pizzaService.emitOrder( this.orderedPizza);

  }

在购物车组件中,我订阅了 ngOnInit 中的更改

  ngOnInit() {

    this.cartService.pizzaOrderEmitter.subscribe(params => {
      var recievedItem: ItemOrder;
      if (params) {
        recievedItem = new ItemOrder(params.id, params.pizza, params.name, params.size, params.listOfAdditions, params.quantity, params.totalPrice);
        this.addItemToOrder(recievedItem);
      } else {
        this.orderedItems = [];
      }
      this.triggerPriceCalculation();
    });

问题是:一旦将商品添加到购物车组件中。它仍然可以通过 Pizza 组件中的 Checkbox 进行操作。虽然在单击复选框时没有发出事件。(添加一个选中一个复选框的项目,然后在将项目添加到购物车后取消选中该复选框或选中另一个复选框)

我知道 Angular 会检查 DOM 更改并更新属性。但是 Pizza 组件正在进行更改,它与 Cart 组件没有直接链接。信息仅使用 Observable 传递。

  <div class="form-group">
                <span class="pull-left"> Ihre Extras:</span><br>
                <div *ngFor="let pizzaAddition of allPizzaAdditions | slice:0:show;let i = index">
                    <input type="checkbox" value=pizzaAddition
                        (change)="fetchPriceForSelectedAddition(allPizzaAdditions[i],pizza, selectedPizzaSize,$event)" />
                    <span> mit {{pizzaAddition.nameOfAddition}}</span>
                    <span>({{displayPizzaAdditionPriceForSelectedPizzaSize(selectedPizzaSize,pizzaAddition.nameOfAddition)==0?pizzaAddition.price:displayPizzaAdditionPriceForSelectedPizzaSize(selectedPizzaSize,pizzaAddition.nameOfAddition)}}€)</span><br>
                    <a *ngIf="i==2 && show == 3" (click)="show = allPizzaAdditions.length">
                        <span class="glyphicon glyphicon-chevron-down"></span>
                    </a>
                </div>
displayPizzaAdditionPriceForSelectedPizzaSize(selectedPizzaSize: HTMLSelectElement, currentPizzaAddition: PizzaAdditions) {
    if (selectedPizzaSize.value.length > 0) {
      return this.pizzaService.fetchPriceOfAPizzaAdditionsAccordingToSize(selectedPizzaSize.value, currentPizzaAddition.id);
    }
    return 0;
  }

In Service


    fetchPriceOfAPizzaAdditionsAccordingToSize(selectedSize: String, selectedAddition: String) {

        switch (selectedSize) {
            case 'Small 26': return 0.50;
            case 'Normal 28': return 1;
            case 'Family 32': return 1.50;
            case 'Party 38': return 2;
            default: return 0.50;
        }

    }

我的期望是,一旦将项目添加到数组中。它不应该以任何方式在外部被操纵,我想知道为什么会这样。

【问题讨论】:

  • 这是一个非常庞大的代码,你能创建最小的问题重现吗?
  • @Plochie 我试过了,但它有很多依赖项。我应该删除其他组件还是您的意思是这两个组件中的代码? PizzaunitComponent 和 CartComponent。
  • 我的意思是整个项目。当您提供如此庞大的代码时,调试需要很长时间。

标签: angular observable


【解决方案1】:

这是因为 JavaScript 中的对象是通过引用传递的。所以pizzaunit.component.ts 中的this.pizzaorderedPizza 对象中的pizza 引用同一个对象。

您可以在onSubmit 中制作比萨的浅拷贝来避免这种情况。 listOfCheckedPizzaAdditions 也必须这样做,它们也是通过引用传递的。

  onSubmit() {
    this.orderedPizza.id = this.pizza.pizzaId;
    this.orderedPizza.pizza= {...this.pizza}; // Shallow copy 
    this.orderedPizza.name = this.pizza.pizzaName;
    this.orderedPizza.quantity = this.selectedQuantity;
    this.orderedPizza.size = this.selectedSize;
    this.orderedPizza.listOfAdditions = [...this.listOfCheckedPizzaAdditions]; // same here
    this.orderedPizza.totalPrice = this.priceOnButton;
    this.pizzaService.emitOrder( this.orderedPizza);
  }

【讨论】:

    【解决方案2】:

    有几种方法可以解决这个问题,但根本原因是你的比萨对象是通过引用传递的。因此,当您在 Pizza 组件中对比萨饼进行更改时,这些更改将反映在 Order 组件中。您想要在链中的某个地方做的是创建一个新的比萨饼对象并将其传递。

    解决此问题的最简单方法很可能是在发出比萨饼之前使用传播运算符。像这样的东西。这将创建比萨对象的副本并将该副本沿链向上传递。因此,您的 Pizza 组件中的 Pizza 对象将与 Order 组件中的不同。

    this.pizzaService.emitOrder({...this.orderedPizza});
    

    【讨论】:

    • 太棒了。感谢您花时间浏览代码。
    猜你喜欢
    • 2021-03-02
    • 1970-01-01
    • 2019-12-31
    • 1970-01-01
    • 2019-01-30
    • 1970-01-01
    • 2018-10-13
    • 1970-01-01
    • 2018-11-06
    相关资源
    最近更新 更多