单击元素按钮时是不是会调用 Angular 8 中的生命周期挂钩

Posted

技术标签:

【中文标题】单击元素按钮时是不是会调用 Angular 8 中的生命周期挂钩【英文标题】:Is there a Lifecycle hook in angular 8 that is called when an elements button is clicked单击元素按钮时是否会调用 Angular 8 中的生命周期挂钩 【发布时间】:2020-04-26 19:38:13 【问题描述】:

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

我有一个服务,它从输入组件中选择值并在服务本身中更新其数组。

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

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

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

我不想使用事件发射器。

父组件

export class ShoppingComponent implements OnInit 
  ingredients:Ingredient[];

  constructor(private shoppingListService: ShoppingListService)  

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

 

父 html

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

父组件中的两个子组件:

列出兄弟姐妹

export class ShoppinglistComponent implements OnInit 
  ingredients: Ingredient[];

  constructor(private shoppingListService: ShoppingListService)  

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


它是 html/模板

<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>

【问题讨论】:

【参考方案1】:

不使用 EventEmitter 会很棘手,CPU 资源消耗和非反应性。让我给你一些建议:

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

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

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

附言:

您确实应该在 ShoppinglisteditComponent 中使用响应式表单或模板驱动表单,因为您想管理表单,而 Angular 做得非常好(不要重新发明***)。下面是一些使用响应式表单的代码(不要忘记包含 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>

【讨论】:

以上是关于单击元素按钮时是不是会调用 Angular 8 中的生命周期挂钩的主要内容,如果未能解决你的问题,请参考以下文章

通过单击按钮从 HTML 调用 Angular2 组件函数

单击时如何使用 Angular js 的 $location.hash 更改 html 元素的颜色?

如何在Angular 7中单击按钮时获取下拉列表的选定选项[重复]

在 Angular 中调用方法时,当前日期变为未定义

Angular JS - 单击按钮从指令加载模板 html

使用子组件按钮单击关闭 Kendo Angular Dialog