首页 > 解决方案 > 什么是更好的方法以及如何实现将对象从一个嵌套组件发送到另一个

问题描述

我正在研究关于产品的简单应用程序,基本上当用户选择产品时,它应该被发送到另一个包含产品的组件。

产品总是一一选择,我从不发送列表!只能逐项

所以基本上当我点击屏幕中间的任何产品(产品食物 1、产品食物 2、产品食物 3)时,它应该被发送到屏幕的右侧,这也是分离的组件。

所以我的中间组件看起来像这样:

<div *ngFor="let product of products;" class="product-holder">
  <div id="product.id" class="product" [style.background]="'url('+ product.imgUrl +')'">
    <p class="product-price">{{product.mpc | number}}</p>
    <p class="product-title">{{product.title}}</p>
  </div>
</div>

还有一个打字稿代码:

@Component({
  selector: 'app-products',
  templateUrl: './app-products.component.html',
  styleUrls: ['./app-products.component.css']
})
export class ProductsComponent implements OnInit {

  products: Article[];

  constructor(private _sharedService: SharedService) { }

  ngOnInit() {
    this._sharedService.getEventSubject().subscribe((param: any) => {
      if (param !== undefined) {
        this.theTargetMethod(param);
      }
    });
  }

  theTargetMethod(param) {
    // Here I am populating middle screen with products 
    this.products = param;
  }
}

现在我将发布我应该收到产品的正确组件:

<div class="order-article">
  <div class="order-img"></div>
  <div class="order-title">
    <p>HERE I SHOULD WRITE ARTILE TITLE</p>
  </div>
  <div class="order-quantity pull-right">
    <span class="order-quantity-number">ARTICLE QUANTITY</span>
  </div>
</div>

export class ReceiptItemComponent implements OnInit {

  constructor() { }

  ngOnInit() {
  }

}

所以这个“正确”的组件应该从中间接收点击的产品,我不知道该怎么做,我对@Input@Output装饰器以及关于services,我猜 @input 和 @output 是正确的解决方案,因为我正在发送一项一项?

但我实际上不知道如何解决这个问题..

任何形式的帮助都会很棒

谢谢

在 fjc 帮助之后:

<div *ngFor="let product of products;" class="product-holder" (click)="addReceiptItem(article)">
  <div id="product.id" class="product" [style.background]="'url('+ product.imgUrl +')'">
    <p class="product-price">{{product.mpc | number}}</p>
    <p class="product-title">{{product.title}}</p>
  </div>
</div>

如您所见,伙计们:

1.)我添加了addReceiptItem方法

2.) 此方法接受点击的产品:

addReceiptItem(receiptItem: Product) {
    this._sharedService.addReceiptItem(receiptItem);
  }

3.)注入服务' _sharedService'并在那里创建的方法也称为'addReceiptItem'

4.)在我的服务中,我BehaviorSubject这样创建: private receiptItem = new BehaviorSubject<any>(undefined);

4.) 服务中的方法如下所示:

addReceiptItem(receiptItems: Product) {
    this.arr1.push(receiptItems);
    this.receiptItem.next(this.arr1);
  }

此方法将单击的项目推送到数组,该数组将发送到显示产品的组件

4.11) 还添加了获取返回 BehaviorSubject 的数据的方法:

getReceiptItem(): BehaviorSubject<any> {
    return this.receiptItem;
  }

5.)显示产品的编辑组件(代码在做任何事情之前也发布了 - 空的打字稿文件),现在看起来像这样:

export class ReceiptItemComponent implements OnInit {

  constructor(private _sharedService: SharedService) { }

  receiptItems: Product[];

  ngOnInit() {
    this._sharedService.getReceiptItem().subscribe(products => this.receiptItems = products);
  }

}

离开只是为了做破坏不知何故?

标签: javascriptangulartypescriptangular-templateangular-decorator

解决方案


有几个策略可以解决这个问题。总的来说,这是一个状态管理问题:多个组件在一个联合状态下工作。

选项 1:父组件管理状态

这可能是最简单的解决方案。

  • 包含所有其他组件的父组件具有选定产品的列表。
  • 让用户选择产品的子组件有一个 @Output() EventEmitter,当用户选择产品时会发出。父组件侦听该输出并将发出的产品添加到其产品列表中。
  • 显示所选产品的子组件具有一个 @Input() 产品数组,它们基于该数组显示产品。父组件将此输入设置为其产品列表。

选项 2:国家服务

快速实现,但比#1 更清晰的关注点分离。

  • 实现一个 @Injectable StateService。它具有 a) a)BehaviorSubject<Product[]>与产品列表,b)addProduct(product: Product)将产品添加到当前值BehaviorSubject并发出它的方法。
  • 每个组件都使用该服务 ( constructor(stateService: StateService))。当用户选择产品时,组件调用this.stateService.addProduct(product).
  • 显示产品的组件监听服务产品列表中的变化:this.stateService.products.subscribe(products => this.products = products)并相应地显示产品。

选项 3:使用 State Store 库

使用像 NGRX 或 Redux 之类的东西来为你处理状态管理。


推荐阅读