为什么ngOnInit打了两次电话?

Shr*_*ree 47 ngoninit angular

我试图创建新的组件,但它的ngOnInit()方法被调用两次,我不知道为什么会发生这种情况?这里我创建了一个名为ResultComponent的组件,它从名为mcq-component的父组件中获取@Input. 这是代码:

父组件(MCQComponent)

import { Component, OnInit } from '@angular/core';

@Component({
    selector: 'mcq-component',
    template: `
        <div *ngIf = 'isQuestionView'>
            .....
        </div>
        <result-comp *ngIf = '!isQuestionView' [answers] = 'ansArray'><result-comp>
    `,
    styles: [
        `
            ....
        `
    ],
    providers: [AppService],
    directives: [SelectableDirective, ResultComponent]
})
export class MCQComponent implements OnInit{
      private ansArray:Array<any> = [];
    ....
    constructor(private appService: AppService){}
    ....
}
Run Code Online (Sandbox Code Playgroud)

子组件(result-comp)

import { Component, OnInit, Input } from '@angular/core';

@Component({
    selector:'result-comp',
    template: `
        <h2>Result page:</h2>

    `
})
export class ResultComponent implements OnInit{
    @Input('answers') ans:Array<any>;

    ngOnInit(){
        console.log('Ans array: '+this.ans);
    }
}
Run Code Online (Sandbox Code Playgroud)

这里控制台日志显示2次:第一次显示正确的数组,但第二次显示未定义,但我无法弄清楚,为什么来自ResultComponent的ngOnInit被调用两次?

Dyl*_*eus 38

为什么它被调用两次

现在,如果在检测到组件的内容/视图子项的更改期间发生错误,则将调用ngOnInit两次(在DynamicChangeDetector中看到).这可能导致隐藏原始错误的后续错误.

此信息来自此github问题


因此,您的错误似乎可能源于您的代码中的其他地方,与此组件相关.

  • 感谢您的回复,这里实际上我只是控制器**isQuestionView**标志,就是这样. (3认同)

ors*_*ady 16

由于组件html错误,这发生在我身上.我忘了关闭主机组件中的选择器标签.所以我有了这个<search><search>,而不是<search></search>- 注意语法错误.

所以与@dylan的答案有关,请检查你的组件html结构及其父组件的结构.


小智 16

如果你platformBrowserDynamic().bootstrapModule(AppModule);在app.module.ts中使用 它评论并尝试.我有同样的问题.我觉得这有帮助


小智 15

在我的案例中,问题是我引导子组件的方式.在我的@NgModule装饰器的元数据对象中,我在bootstap属性中传递' child component ' 和' parent component '.在bootstap属性中传递子组件是重置我的子组件属性并使OnInit()触发两次.

@NgModule({
imports: [ BrowserModule,FormsModule ], // to use two-way data binding ‘FormsModule’
declarations: [ parentComponent,Child1,Child2], //all components
//bootstrap: [parentComponent,Child1,Child2] // will lead to errors in binding Inputs in Child components
bootstrap: [parentComponent] //use parent components only
})
Run Code Online (Sandbox Code Playgroud)


Mai*_*jat 11

ngOnInit()在所有指令都被实例化后,钩子只挂一次。如果您有订阅ngOnInit()并且它没有取消订阅,那么如果订阅的数据发生变化,它将再次运行。

在下面的 Stackblitz 示例中,我有订阅ngOnInit()并控制结果。它控制台两次,因为它加载一次,数据发生变化,然后再次加载。

闪电战

  • 不,不是,它只记录一次。输出是“Angular”、“Angular8”,然后是“p”。`p` 只被记录一次。 (2认同)

小智 10

把这个放在这里以防万一有人在这里结束.如果您的浏览器的默认按钮类型是"提交",NgOnInit也可以被调用两次,如果您有以下内容,则在Chrome中将调用两次NextComponent的NgOnInit:

<button class="btn btn-primary" (click)="navigateToNextComponent()">
Run Code Online (Sandbox Code Playgroud)

要修复它,请设置类型:

<button class="btn btn-primary" type="button" (click)="navigateToNextComponent()">
Run Code Online (Sandbox Code Playgroud)

  • 谢谢,这正是我的情况的问题。不过,我想只有当您的按钮是“&lt;form&gt;”的一部分时,这才有意义。 (2认同)

Was*_*siF 7

这可能是因为您将设置AppComponent为默认路线

RouterModule.forRoot([
    { path: '', component: AppComponent }  // remove it
])
Run Code Online (Sandbox Code Playgroud)

注意:AppComponent默认情况下被调用,angular因此无需调用它


Bha*_*Raj 5

每当有任何模板错误时就会发生这种情况。

就我而言,我使用了错误的模板参考并进行更正,从而解决了我的问题。

  • 您能详细说明一下“模板错误”吗?也许举个例子。 (2认同)

dan*_*y74 5

如果您有多个路由器插座,则可能会发生这种情况:

<ng-container *ngIf="condition">
  <div class="something">
    <router-outlet></router-outlet>
  </div>
</ng-container>
<ng-container *ngIf="!condition">
  <div class="something-else">
    <router-outlet></router-outlet>
  </div>
</ng-container>
Run Code Online (Sandbox Code Playgroud)

请注意,如果这样做,它最终也可能会调用构造函数两次。构造函数被调用两次的事实证明该组件被创建了两次,这正是当组件位于其*ngIf条件从 true 到 false 再到 true 的内部时发生的情况

调试此问题的一个有用方法是创建一个名为 rnd 的类变量,如下所示:

rnd = Math.random()
Run Code Online (Sandbox Code Playgroud)

并在构造函数和 ngOnInit 中 console.log 。如果值发生变化,那么您在第二次调用时就知道这是该组件的一个新实例,并且调用的实例不是同一个实例。虽然这不能解决您的问题,但它可能表明问题所在。