angular 8 中是否有单击元素按钮时调用的生命周期挂钩

Is there a Lifecycle hook in angular 8 that is called when an elements button is clicked

我有一个包含两个嵌套组件的主组件,其中一个组件包含输入字段 (2) 和一个用于添加项目的按钮,另一个同级组件循环显示项目。

我有一项服务可以从输入组件中选取值并在服务本身中更新其数组。

每当我填写输入并提交服务时,都会将新项目添加到数组中,但我需要更新需要显示此列表的同级组件。

我知道我必须从服务中获取值,因为它有更新的数组。

我不知道我可以在列表同级组件中使用哪个生命周期钩子来获取新列表,因为点击添加按钮时似乎没有调用 ngOnInit。

我不想使用事件发射器。

Parent 组件

export class ShoppingComponent implements OnInit {
  ingredients:Ingredient[];

  constructor(private shoppingListService: ShoppingListService) { }

  ngOnInit() {
    this.ingredients = this.shoppingListService.getIngredients();
  }

} 

parent html

<div class="row">
    <div class="col-md-10">
        <app-shoppinglistedit></app-shoppinglistedit>
        <hr>
        <app-shoppinglist></app-shoppinglist>
    </div>
</div>

两个child组件放在parent组件中:

列出兄弟姐妹

export class ShoppinglistComponent implements OnInit {
  ingredients: Ingredient[];

  constructor(private shoppingListService: ShoppingListService) { }

  ngOnInit() {
    this.ingredients = this.shoppingListService.getIngredients();
    this.oldLength = this.ingredients.length;
  }

}

是html/template

<ul class="list-group">
    <a class="list-group-item" *ngFor="let ingridient of ingredients" >
        {{ ingridient.name }} <span class="badge badge-success badge-pill ml-auto">{{ ingridient.amount }}</span>
    </a>
</ul>

添加兄弟姐妹

export class ShoppinglisteditComponent implements OnInit {
  @ViewChild('nameRef', {static: true}) itemName:ElementRef;
  @ViewChild('amountRef', {static: true}) itemAmount:ElementRef;

  constructor(private shoppingListService: ShoppingListService) { }

  ngOnInit() {
  }

  onAddNewItem(){
    const name = this.itemName.nativeElement.value;
    const amount = +this.itemAmount.nativeElement.value;
    const ingredient = new Ingredient(name, amount);

    this.shoppingListService.addIngredient(ingredient);
    console.log("All ingredients: ");
    console.log(this.shoppingListService.getIngredients());

  }
}

这是模板 - html

<div class="row col-sm-12">
    <form>
        <div class="row">
            <div class="form-group col-sm-5">
                <label for="name">Name</label>
                <input id="name" class="form-control" type="text" name="name" #nameRef>
            </div>
            <div class="form-group col-sm-2">
                <label for="amount">Amount</label>
                <input id="amount" class="form-control" type="number" name="amount" #amountRef>
            </div>
        </div>
        <div class="row">
            <div class="col-md-12">
                <button class="btn btn-success mr-2" type="button" (click)="onAddNewItem()">
                    <i class="fas fa-plus-circle"></i>&nbsp;Add Item
                </button>
                <button class="btn btn-danger mx-2" type="button">
                    <i class="far fa-trash-alt" (click)="onDeleteIngredient()"></i>&nbsp;Delete Item
                </button>
                <button class="btn btn-primary mx-2" type="button">
                    <i class="fas fa-adjust" (click)="onClearItem()"></i>&nbsp;Clear Item
                </button>
            </div>
        </div>
    </form>
</div>

不使用 EventEmitter 会很棘手,CPU 资源消耗和非反应性。让我向你推荐一些东西:

首先为您的组件 ShoppinglistComponent 创建一个 @Input() ingredients: Ingredient[]。您已经在父组件中获取了成分,因此您可以将它们传递给任何子组件(在我们的例子中是 ShoppinglistComponent) 然后将 @Output() ingredientAdded = new EventEmitter() 添加到您的组件 ShoppinglisteditComponent 中,您将在 onAddNewItem 方法中触发它。 在您的 ShoppinglistComponent 中收听输出 (ingredientAdded)="insertNewIngredient($event)"

insertNewIngredient(addedIngredient: Ingredient): void {
  this.ingredients = this.ingredients.concat(addedIngredient)
}

当您通过输入将成分传递给 ShoppinglistComponent 时,它会自动更新您的视图。不需要生命周期钩子,只需使用一些公平的反应代码。

P-S:

您真的应该在 ShoppinglisteditComponent 中使用响应式表单或模板驱动表单,因为您想要管理表单并且 Angular 做得非常好(不要t重新发明轮子)。这是一些使用 Reactive 表单的代码(不要忘记包含 FormsModuleReactiveFormsModule

  form: FormGroup;

  constructor(
    fb: FormBuilder,
    private shoppingListService: ShoppingListService
  ) {
    this.form = fb.group({
      name: ['', Validator.required],
      amount: [0, [Validator.required, Validator.min(0)]]
    })
  }

  onAddNewItem(){
    const { name, amount } = this.form.value;
    const ingredient = new Ingredient(name, amount);
    this.shoppingListService.addIngredient(ingredient);
    console.log("All ingredients: ");
    console.log(this.shoppingListService.getIngredients());
  }
<div class="row col-sm-12">
    <form [formGroup]="form" (ngSubmit)="onAddNewItem()">
        <div class="row">
            <div class="form-group col-sm-5">
                <label for="name">Name</label>
                <input formControlName="name" id="name" class="form-control" type="text" required>
            </div>
            <div class="form-group col-sm-2">
                <label for="amount">Amount</label>
                <input formControlName="amount" id="amount" class="form-control" type="number" required>
            </div>
        </div>
        <div class="row">
            <div class="col-md-12">
                <button class="btn btn-success mr-2">
                    <i class="fas fa-plus-circle"></i>&nbsp;Add Item
                </button>
                <button class="btn btn-danger mx-2" type="button">
                    <i class="far fa-trash-alt" (click)="onDeleteIngredient()"></i>&nbsp;Delete Item
                </button>
                <button class="btn btn-primary mx-2" type="button">
                    <i class="fas fa-adjust" (click)="onClearItem()"></i>&nbsp;Clear Item
                </button>
            </div>
        </div>
    </form>
</div>