简体   繁体   English

Angular ngOnInit 不适用于子组件

[英]Angular ngOnInit not working for the child component

Please have a look at the Stackblitz Editor link.请查看Stackblitz 编辑器链接。 I've set up one angular application.我已经设置了一个角度应用程序。

Brief working overview of the angular app angular 应用程序的简要工作概述

  • Two components ie app-component and child-component两个组件,即 app-component 和 child-component
  • Initially, child component not display.最初,子组件不显示。 There is a button in the parent app component when we click on the button, we enable one variable 'this.showChildComponent = true'.当我们点击按钮时,父应用组件中有一个按钮,我们启用一个变量'this.showChildComponent = true'。
  • child component controlled by the variable this.showChildComponent.由变量 this.showChildComponent 控制的子组件。
  • I'm using the 'firstParam' and 'secondParam' as a variable and sending these variables values to the child component.我使用“firstParam”和“secondParam”作为变量并将这些变量值发送到子组件。

Now, Please have a look at the issue现在,请看一下问题

When we click on the button as I explained above, child component mounted and ngOnInit method will be called, you can also check the message on the console screen ' ngOnInit called: child component ' but if I again click on the button, then the child component not re-render again and thus, ngOnInit method of child component not called.当我们像上面解释的那样点击按钮时,子组件会挂载并调用 ngOnInit 方法,您还可以检查控制台屏幕上的消息“ ngOnInit 调用:子组件”但如果我再次单击按钮,则子组件组件不会再次重新渲染,因此不会调用子组件的 ngOnInit 方法。

// This method is defined in the app-component (parent) and it is called when user clicks on 
// button
showChild() {
    if (this.showChildComponent)
    {
      this.showChildComponent = false;
    }
    this.showChildComponent = true;
    // child component ngOnInit call when
    // I use the timer
    // setTimeout(()=> {this.showChildComponent = true;}, 10);
    this.firstParam = 'first param from parent';
    this.secondParam = 'second param from parent';
  }

// Parent component - app-component
<button (click)="showChild()">Click here to display the child component</button>

<div *ngIf="showChildComponent">
  <app-child-component
    [first_param]="firstParam"
    [second_param]="secondParam"
  ></app-child-component>
</div>

As you can see in the code, if I use the setTimeout then child component ngOnInit method will be called whenever I click on the parent component button.正如您在代码中看到的,如果我使用 setTimeout,那么每当我单击父组件按钮时,都会调用子组件 ngOnInit 方法。 But I don't want to use the timer here, what is the alternative solution to resolve this issue?但是我不想在这里使用计时器,解决此问题的替代解决方案是什么? whenever user clicks on the button, ngOnInit method of child component should be call.每当用户单击按钮时,应调用子组件的 ngOnInit 方法。

Try this one to toggle your component:试试这个来切换你的组件:

  showChild() {
    this.showChildComponent = !this.showChildComponent;
    this.firstParam = 'first param from parent';
    this.secondParam = 'second param from parent';
  }

Copied from comment to give a bit of reference for the answer:从评论中复制以提供一些参考答案:

You have set it to false and then true before the change detection has had a chance to read that there is a change.在更改检测有机会读取有更改之前,您已将其设置为 false 和 true。 This means that the child component will not be removed and then re-added.这意味着子组件不会被删除然后重新添加。 This is why it works by using a timeout, because the timeout will get executed after the change detection.这就是它使用超时的原因,因为超时将在更改检测后执行。 If you really want the behavior to run in the ngOnInit then you would need to use a settimeout to wait for the component to be destroyed.如果您真的希望该行为在 ngOnInit 中运行,那么您将需要使用 settimeout 来等待组件被销毁。

Since it seems that you don't want to use the setTimeout, even though that's how I'd suggest doing it, you can force the change detection using one of the methods provided here .由于您似乎不想使用 setTimeout,即使我建议这样做,您也可以使用此处提供的方法之一强制更改检测。 Here is a stackblitz fork from your original question, using the third approach.这是使用第三种方法的原始问题的stackblitz分支。

You need to add some additional condition to your if statement.您需要在if语句中添加一些额外的条件。 Right now, the logic always assigns this.showChildComponent to true (even after you've assigned it to false ).现在,逻辑总是将this.showChildComponent分配给true (即使在您将它分配给false )。 Change your showChild method to:将您的showChild方法更改为:

showChild() {
    if (this.showChildComponent)
    {
      this.showChildComponent = false;
    } else {
      this.showChildComponent = true;
    }
    // child component ngOnInit call when
    // I use the timer
    // setTimeout(()=> {this.showChildComponent = true;}, 10);
    this.firstParam = 'first param from parent';
    this.secondParam = 'second param from parent';
  }

You were previously always setting the showChildComponent attribute to true and never were destroying the child.您以前总是将showChildComponent属性设置为true并且从未销毁子项。 Thus, it was never re-rendering.因此,它永远不会重新渲染。

For this you can manually trigger the child component by using ChangeDetectorRef为此,您可以使用ChangeDetectorRef手动触发子组件

Create an instance of ChangeDetectorRef and use like this below in app component.创建一个ChangeDetectorRef实例并在应用组件中像下面这样使用。

this.changeDetectorRef.detectChanges(); this.changeDetectorRef.detectChanges();

Or Alternative way to achieve this is to use ngOnChanges , which will change everytime when you pass params as Input to child component.或者实现此目的的替代方法是使用ngOnChanges ,每次将 params 作为 Input 传递给子组件时都会更改。 Here is a stackblitz fork by using ngOnChanges lifecycle hook.这是一个使用 ngOnChanges 生命周期钩子的stackblitz分支。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM