构造函数和ngOnInit之间的区别


Answers:


1107

Constructor是该类的默认方法,该方法在实例化该类时执行,并确保正确初始化该类及其子类中的字段。角度更好的依赖项注入器(DI),分析构造函数参数,并在通过调用它创建新实例new MyClass()时尝试查找与构造函数参数类型匹配的提供程序,将其解析并将其传递给构造函数,例如

new MyClass(someArg);

ngOnInit 是Angular调用的生命周期挂钩,以指示Angular已完成创建组件。

OnInit为了使用它,我们必须像这样导入(实际上实施OnInit不是强制性的,但被认为是好的做法):

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

然后要使用使我们成为该方法OnInit,我们必须实现这样的类:

export class App implements OnInit {
  constructor() {
     // Called first time before the ngOnInit()
  }

  ngOnInit() {
     // Called after the constructor and called  after the first ngOnChanges() 
  }
}

在初始化指令的数据绑定属性之后,实现此接口以执行自定义初始化逻辑。ngOnInit在第一次检查指令的数据绑定属性之后以及在检查其子项之前立即调用。实例化指令后,仅调用一次。

通常,我们ngOnInit用于所有初始化/声明,并避免在构造函数中工作。构造函数应仅用于初始化类成员,而不应执行实际的“工作”。

因此,您应该使用它constructor()来设置依赖项注入,而无需过多设置。ngOnInit()是“开始”的更好位置-解析组件绑定的位置/位置。

有关更多信息,请参见此处:


62
确实,大多数(甚至所有)基于类的语言都具有构造函数,以确保正确的初始化顺序,特别是那些扩展了其他类的类,这些类可能会遇到一些非常困难的问题,例如final字段(不知道TS是否包含它们)等。构造函数与Angular2无关,它们是TypeScript功能。在进行一些初始化或发生某些事件以允许组件在某些情况下起作用并使其有机会在适当的时候执行某些任务之后,Angular会调用生命周期挂钩。
君特Zöchbauer

12
angular.io/docs/ts/latest/guide/server-communication.html中有一个引用的块,它也解释了这一点:“组件的构造函数很简单,并且所有实际工作(特别是调用a远程服务器)以单独的方法处理。” -在这种情况下,该方法为ngOnInit()
yoonjesung

3
是Angular2调用的生命周期挂钩,以指示Angular已完成组件的创建。-那不完全是。它表示已初始化绑定。该组件是较早创建的。看到我的回答
Max Koretskyi

22
与所有“最佳实践”一样,我认为最好解释一下为什么不应该在构造函数中进行“工作”。Angular团队负责人撰写的这篇文章内容丰富 ,但可能会有所帮助:misko.hevery.com/code-reviewers-guide / ...此外,对于实现OnInit所需的技巧(这很容易找到)的重视程度应不那么重要,而更多内容关键事实是数据绑定在构造函数中不可用。
灵气

2
如果严格模式在tsconfig.jsonlike文件中为true "strict": true,那么您必须在中而constructor不是ngOnitlike中初始化类成员FormGroup
罗希特·夏尔马

169

文章Angular中的Constructor和ngOnInit之间的本质区别从多个角度探讨了这一区别。该答案提供了与组件初始化过程有关的最重要的差异说明,还说明了用法上的差异。

角引导程序包括两个主要阶段:

  • 构造组件树
  • 运行变化检测

当Angular构造组件树时,将调用组件的构造函数。所有生命周期挂钩都称为运行更改检测的一部分。

当Angular构造组件树时,已经配置了根模块注入器,因此您可以注入任何全局依赖项。另外,当Angular实例化子组件类时,还已经为父组件设置了注入器,因此您可以注入在父组件上定义的提供者,包括父组件本身。组件构造函数是在注入器上下文中唯一被调用的方法,因此,如果您需要任何依赖关系,那么它是获取这些依赖关系的唯一位置。

当Angular开始更改检测时,将构建组件树,并已调用树中所有组件的构造函数。同样,每个组件的模板节点都添加到DOM中。该@Input所以你不能指望在构造函数提供的属性的通信机制是改变检测过程中处理。将在之后可用ngOnInit

让我们来看一个简单的例子。假设您具有以下模板:

<my-app>
   <child-comp [i]='prop'>

因此,Angular开始引导应用程序。如我所说,它首先为每个组件创建类。因此它称为MyAppComponent构造函数。它还创建一个DOM节点,该节点是my-app组件的宿主元素。然后,继续为child-comp和调用ChildComponent构造函数创建一个host元素。在此阶段,它并不真正关心i输入绑定和任何生命周期挂钩。因此,完成此过程后,Angular最终得到以下组件视图树:

MyAppView
  - MyApp component instance
  - my-app host element data
       ChildCompnentView
         - ChildComponent component instance
         - child-comp host element data  

只有这样运行的变化检测和更新绑定my-app和调用ngOnInit上MyAppComponent类。然后,它继续更新和的绑定,child-comp并调用ngOnInitChildComponent类。

您可以在构造函数中进行初始化逻辑,也可以ngOnInit根据需要进行初始化。例如,本文“ 如何在评估@ViewChild查询之前获取ViewContainerRef”显示了在构造函数中可能需要执行哪种类型的初始化逻辑。

以下是一些文章,可以帮助您更好地理解该主题:


33
这应该是公认的答案。它实际上是在解释原因,而不是重复咒语和陈述the constructor should only be used to inject dependencies
Stavm '17

1
@ yannick1976,谢谢!看看引用的文章
Max Koretskyi,

@flobacca,能否请您改一下这个问题,很难理解您的要求
Max Koretskyi

如果我错了,请纠正我。我了解到,首先要构建组件树,然后更改检测过程。您首先编写了AppComponent构造函数(以及已解决的依赖关系),然后调用了ChildComponent构造函数(以及依赖关系),然后调用了AppComponent的输入绑定,然后调用了OnInit。但是我担心的是,如果我将生命周期挂钩添加到这两个组件,则流程为AppComponentConstructor —-> AppComponentOnInit —→ChildComponentConstructor —→ChildComponentOnInit为什么在ChildComponentConstructor之前调用AppComponentOnInit
user2485435

1
@MaxKoretskyiakaWizard你是对的。我在应用程序设置中犯了一些错误。它按您描述的那样工作。 angular-c7zjsx.stackblitz.io
user2485435 '19

93

我认为最好的例子就是使用服务。假设我要在我的组件被“激活”时从服务器中获取数据。假设从服务器获取数据后,我还想对数据做一些其他事情,也许我遇到错误并希望以其他方式记录它。

在构造函数上使用ngOnInit确实很容易,它还限制了我需要添加到应用程序中的回调层数。

例如:

export class Users implements OnInit{

    user_list: Array<any>;

    constructor(private _userService: UserService){
    };

    ngOnInit(){
        this.getUsers();
    };

    getUsers(){
        this._userService.getUsersFromService().subscribe(users =>  this.user_list = users);
    };


}

使用我的构造函数,我可以只调用_userService并填充我的user_list,但也许我想用它做一些额外的事情。就像确保所有内容都是大写一样,我也不完全确定我的数据是如何传递的。

因此,它使使用ngOnInit变得更加容易。

export class Users implements OnInit{

    user_list: Array<any>;

    constructor(private _userService: UserService){
    };

    ngOnInit(){
        this.getUsers();
    };

    getUsers(){
        this._userService.getUsersFromService().subscribe(users =>  this.user_list = users);
        this.user_list.toUpperCase();
    };


}

它使查看起来更加容易,因此我在初始化时就在组件内调用函数,而不必在其他地方进行挖掘。确实,它只是您可以用来使将来更易于阅读和使用的另一种工具。另外,我发现将函数调用放在构造函数中实在是一种不好的做法!


如果仅将user_list设置为Observable,则可以简化示例。Angular2具有异步管道,因此那里不会有任何问题。
DarkNeuron

@Morgan,只是为了让我在这里学习一点东西,为什么您首先创建一个函数getUsers然后将其插入ngOnInit?仅用ngOnInit编写代码就不少吗?我很想知道为什么人们这样做吗?这样是否也可以重用代码?谢谢。
阿尔法·布拉沃

31
如下面的答案所示,如果它在构造函数中,则没有任何区别。这不是达到目的的真正答案。
Jimmy Kane

8
我完全看不出如何回答这个问题。为什么不把代码放进constructor去呢?
CodyBugstein

1
@摩根,你为什么不能做constructor(private _userService: UserService){ this.getUsers(); };
阿什利

82

好的,首先ngOnInitAngular生命周期的一部分,而又constructorES6 JavaScript类的一部分,因此主要区别就从这里开始!

查看我创建的下图,该图显示了Angular的生命周期。

ngOnInit与构造函数

在Angular2 +中,我们constructor通常DI(Dependency Injection)为我们做,而在Angular 1中,这是通过调用String方法并检查注入了哪些依赖项来实现的。

如您在上图中所看到的,它ngOnInit是在构造函数准备好之后发生的,ngOnChnages并在组件为我们准备好之后被解雇了。所有初始化都可以在此阶段发生,一个简单的示例就是注入服务并在init上对其进行初始化。

好的,我还分享了一个示例代码供您查看,看看我们如何在以下代码中使用ngOnInitconstructor

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


@Component({
 selector: 'my-app',
 template: `<h1>App is running!</h1>
  <my-app-main [data]=data></<my-app-main>`,
  styles: ['h1 { font-weight: normal; }']
})
class ExampleComponent implements OnInit {
  constructor(private router: Router) {} //Dependency injection in the constructor

  // ngOnInit, get called after Component initialised! 
  ngOnInit() {
    console.log('Component initialised!');
  }
}

1
谢谢。这应该是最好的答案。
Don Dilanga

58

第一个(构造函数)与类实例化相关,与Angular2无关。我的意思是,构造函数可以在任何类上使用。您可以对新创建的实例进行一些初始化处理。

第二个对应于Angular2组件的生命周期挂钩:

从Angular官方网站引用:

  • ngOnChanges 输入或输出绑定值更改时调用
  • ngOnInit 在第一个之后被调用 ngOnChanges

因此,ngOnInit如果初始化处理依赖于组件的绑定(例如,用定义的组件参数@Input),则应该使用,否则构造函数就足够了……


49

我只会添加一个在上面的说明中跳过的重要事项,并说明您必须使用的时间ngOnInit

如果要通过ViewChildrenContentChildrenElementRef对组件的DOM进行任何操作,则在构造器阶段将无法使用本机元素。

但是,由于ngOnInit一旦创建了组件并ngOnChanges调用了checks()之后,您现在就可以访问DOM。

export class App implements OnInit, AfterViewInit, AfterContentInit {
  @Input() myInput: string;
  @ViewChild() myTemplate: TemplateRef<any>;
  @ContentChild(ChildComponent) myComponent: ChildComponent; 

  constructor(private elementRef: ElementRef) {
     // this.elementRef.nativeElement is undefined here
     // this.myInput is undefined here
     // this.myTemplate is undefined here
     // this.myComponent is undefine here
  }

  ngOnInit() {
     // this.elementRef.nativeElement can be used from here on
     // value of this.myInput is passed from parent scope
     // this.myTemplate and this.myComponent are still undefined
  }
  ngAfterContentInit() {
     // this.myComponent now gets projected in and can be accessed
     // this.myTemplate is still undefined
  }

  ngAfterViewInit() {
     // this.myTemplate can be used now as well
  }
}

3
不。对于@ViewChildren特别,您需要使用ngAfterViewInit方法。在这里看到:stackoverflow.com/questions/46314734/...
AsGoodAsItGets

1
谢谢@AsGoodAsItGets指出来。我现在已经改善了答案
Miroslav Jonas

38

简单而简单的答案是,

Constructorconstructor是在构造组件时的default method运行(默认)。当您创建an instance一个类时,也constructor(default method)将调用该时间。因此,换句话说,正在constructed or/and an instance is created constructor(default method)调用组件时,将调用其中编写的相关代码。基本上并且通常Angular2用于注入事物,例如services在构造组件以供进一步使用时。

OnInit:ngOnInit是组件的生命周期挂钩,constructor(default method)在初始化组件后首先运行。

因此,将首先调用构造函数,然后在构造函数方法之后调用Oninit。

引导程序

import {Cmomponent, OnInit} from 'angular2/core';
import {ExternalService} from '../externalService';

export class app implements OnInit{
   constructor(myService:ExternalService)
   {
           this.myService=myService;
   }

   ngOnInit(){
     // this.myService.someMethod() 
   }
}

资源:LifeCycle挂钩

您可以查看这个小样的演示,它演示了两者的实现。


5
我认为“构造函数是在初始化组件时运行或调用的东西”。有误导性。构造函数是类的功能,而不是组件的功能。我想说的类的实例才能成为构造函数被调用后,组件角度做了的初始化。
君特Zöchbauer

是的,您可以立即检查该语句。
micronyks '16

1
嗯,恕我直言,它仍然是“构造器(默认方法)是在构造组件时运行或调用的东西”。它不仅在构造组件时调用,而且在服务或类似代码new MyClass()的执行时调用。我认为说构造函数是关于组件,它们是关于类以及初始化这些类的实例是一种误导。一个组件恰好就是这样的一类。否则,我认为这是一个很好的答案。
君特Zöchbauer

2
是的,一点没错。忘了提及,当您创建类的对象时,constructor也会调用该时间。但是,这个答案是在angular2上下文中编写的。要知道最佳答案,您必须了解OOP的基础知识。我还是会更新答案。
micronyks '16

@GünterZöchbauer,我认为这不是一个正确的断言,它是类的功能而不是组件的功能。从编程语言的角度来看,是的,这是正确的。但是我可以完全不用任何生命周期挂钩而成功地使用组件。但是,如果我需要DI,就无法使用没有构造函数的组件,因为那是唯一可注射的地方。看到我的回答
Max Koretskyi

20

与许多其他语言一样,您可以在类级别,构造函数或方法上初始化变量。由开发人员决定在特定情况下哪种最佳。但是,以下是有关决策的最佳做法的列表。

类级变量

通常,您将在此处声明所有变量,这些变量将在其余组件中使用。如果值不依赖其他任何内容,则可以对其进行初始化;如果它们不变,则可以使用const关键字创建常量。

export class TestClass{
    let varA: string = "hello";
}

建设者

通常,最佳做法是在构造函数中不执行任何操作,而仅将其用于将要注入的类。大多数时候,您的构造函数应如下所示:

   constructor(private http: Http, private customService: CustomService) {}

这将自动创建类级别的变量,因此您customService.myMethod()无需手动即可访问。

NgOnInit

NgOnit是Angular 2框架提供的生命周期挂钩。您的组件必须实现OnInit才能使用。在调用构造函数并初始化所有变量之后,将调用此生命周期挂钩。您的大部分初始化工作应在此处进行。您可以确定Angular已正确初始化了组件,并且可以在OnInit组件未正确加载时开始执行所需的任何逻辑操作。

这是一张详细说明调用顺序的图像:

在此处输入图片说明

https://angular.io/docs/ts/latest/guide/lifecycle-hooks.html

TLDR

如果您使用的是Angular 2框架,并且需要与某些生命周期事件进行交互,请使用该框架提供的方法来避免问题。


19

为了测试这一点,我编写了以下代码,借鉴了NativeScript教程

用户名

export class User {
    email: string;
    password: string;
    lastLogin: Date;

    constructor(msg:string) {        
        this.email = "";
        this.password = "";
        this.lastLogin = new Date();
        console.log("*** User class constructor " + msg + " ***");
    }

    Login() {
    }
}

login.component.ts

import {Component} from "@angular/core";
import {User} from "./../../shared/user/user"

@Component({
  selector: "login-component",
  templateUrl: "pages/login/login.html",
  styleUrls: ["pages/login/login-common.css", "pages/login/login.css"]
})
export class LoginComponent {

  user: User = new User("property");  // ONE
  isLoggingIn:boolean;

  constructor() {    
    this.user = new User("constructor");   // TWO
    console.log("*** Login Component Constructor ***");
  }

  ngOnInit() {
    this.user = new User("ngOnInit");   // THREE
    this.user.Login();
    this.isLoggingIn = true;
    console.log("*** Login Component ngOnInit ***");
  }

  submit() {
    alert("You’re using: " + this.user.email + " " + this.user.lastLogin);
  }

  toggleDisplay() {
    this.isLoggingIn = !this.isLoggingIn;
  }

}

控制台输出

JS: *** User class constructor property ***  
JS: *** User class constructor constructor ***  
JS: *** Login Component Constructor ***  
JS: *** User class constructor ngOnInit ***  
JS: *** Login Component ngOnInit ***  

18

构造函数之间的主要差异,ngOnInit就是ngOnInit生命周期挂钩,并构造后运行。组件插值模板和输入初始值在构造函数中不可用,但在中可用ngOnInit

实际的区别在于如何ngOnInit影响代码的结构。大多数初始化代码都可以移至ngOnInit- 只要不创建竞争条件即可

构造函数反模式

大量的初始化代码使构造方法难以扩展,读取和测试。

将初始化逻辑与类构造函数分离的通常方法是将其移至另一个方法,例如init

class Some {
  constructor() {
    this.init();
  }

  init() {...}
}

ngOnInit 可以在组件和指令中达到此目的:

constructor(
  public foo: Foo,
  /* verbose list of dependencies */
) {
  // time-sensitive initialization code
  this.bar = foo.getBar();
}

ngOnInit() {
  // rest of initialization code
}

依赖注入

Angular中类构造函数的主要作用是依赖注入。构造函数还用于TypeScript中的DI注释。几乎所有依赖项都作为属性分配给类实例。

平均组件/指令构造函数已经足够大,因为由于依赖关系,它可能具有多行签名,因此将不必要的初始化逻辑放入构造函数主体中会构成反模式。

异步初始化

异步初始化构造函数通常被认为是反模式,并且有气味,因为类实例化在异步例程执行之前完成,这会创建竞争条件。如果不是这种情况,那么ngOnInit其他生命周期挂钩将是更好的选择,尤其是因为它们可以从async语法中受益:

constructor(
  public foo: Foo,
  public errorHandler: ErrorHandler
) {}

async ngOnInit() {
  try {
    await this.foo.getBar();
    await this.foo.getBazThatDependsOnBar();
  } catch (err) {
    this.errorHandler.handleError(err);
  }
}

如果存在竞争条件(包括在初始化错误时不应出现组件的竞争条件),则应在组件实例化之前进行异步初始化例程,并将其移至父组件,路由器防护等。

单元测试

ngOnInit比构造器更灵活,并为单元测试提供了一些好处,该答案对此有详细解释。

考虑到ngOnInit在单元测试中不会在组件编译时自动调用该方法,因此ngOnInit可以在组件实例化之后对被调用的方法进行间谍或模拟。

在特殊情况下,ngOnInit可以完全存根以提供其他组件单元的隔离(例如,某些模板逻辑)。

遗产

子类只能扩充构造函数,而不能代替它们。

由于this之前无法引用super(),因此对初始化优先级设置了限制。

考虑到Angular组件或指令用于ngOnInit对时间不敏感的初始化逻辑,子类可以选择是否super.ngOnInit()调用以及何时调用:

ngOnInit() {
  this.someMethod();
  super.ngOnInit();
}

仅使用构造函数无法实现。


12

上面的答案并没有真正回答原始问题的这一方面:什么是生命周期挂钩?我花了一段时间才明白这意味着什么,直到我这样思考。

1)说您的组成部分是人。人类的生活包括许多生活阶段,然后我们死亡。

2)我们的人类组成部分可能具有以下生命周期脚本:出生,婴儿,小学,青年,中年成年人,高级成年人,死亡,被处置。

3)假设您要具有创建子代的功能。为了避免复杂化和幽默化,您希望仅在人类组件生命的“年轻成人”阶段调用函数。因此,您开发的组件仅在父组件处于“年轻成人”阶段时才处于活动状态。挂钩可以指示生命的各个阶段并让您的组件对其进行操作,从而帮助您实现这一目标。

好玩的东西。如果让您的想象力去实际编码这样的东西,它将变得复杂而有趣。


7

构造函数是在JavaScript的方法,被认为是在ES6类的功能。当类实例化它立即运行构造无论是在角框架中使用或not.So它是由JavaScript引擎叫和角度没有控制。

import {Component} from '@angular/core';
@Component({})
class CONSTRUCTORTEST {

//This is called by Javascript not the Angular.
     constructor(){
        console.log("view constructor initialised");
     }
}

下面实例化了“ ConstructorTest”类;因此它在内部调用了构造函数(所有这些都通过JavaScript(es6)no Angular发生)。

new CONSTRUCTORTEST();

这就是为什么Angular中存在ngOnInit生命周期挂钩的原因。当Angular完成组件初始化后,ngOnInit就会呈现。

import {Component} from '@angular/core';
@Component({})
class NGONINITTEST implements onInit{
   constructor(){}
   //ngOnInit calls by Angular
   ngOnInit(){
     console.log("Testing ngOnInit");
   }
}

首先,我们实例化以下类,该类发生在构造函数方法的立即运行中。

let instance = new NGONINITTEST();

必要时,Angular会调用ngOnInit,如下所示:

instance.ngOnInit();

但是您可能会问为什么我们在Angular中使用构造函数?

答案是依赖项注入。正如前面提到的,构造函数在实例化类时立即由JavaScript引擎调用构造函数(在通过Angular调用ngOnInit之前),因此typescript帮助我们获取依赖项的类型是在构造函数中定义的,并最终告诉角我们要在该特定组件中使用哪种类型的依赖项。


7

这里要注意两件事:

  1. 每当创建该类的对象时,就会调用构造函数。
  2. 组件创建后即调用ngOnInit。

两者都有不同的可用性。


5

Constructor()是组件生命周期中的默认方法,用于依赖项注入。构造函数是一个打字稿功能。

在构造函数之后调用ngOnInit(),在第一个ngOnChanges之后调用ngOnInit。

即:

构造函数()-->ngOnChanges()-->ngOnInit()

ngOnChanges()当输入或输出绑定值更改时,将调用上述方法。


4

两种方法都有不同的目标/职责。构造函数(这是语言支持的功能)的任务是确保表示形式不变。否则,通过为成员提供正确的值来确保实例有效。由开发人员决定“正确”的含义。

onInit()方法(这是一个有角度的概念)的任务是允许在正确的对象(表示形式不变)上进行方法调用。每个方法应依次确保方法终止时表示形式不变。

构造函数应用于创建“正确的”对象,onInit方法使您有机会在定义良好的实例上调用方法调用。


4

构造函数: ES6类(在这种情况下为TypeScript)上的构造函数方法是类本身的功能,而不是Angular功能。调用构造函数时,它不在Angular的控制范围内,这意味着当Angular完成组件初始化时,它不是让您知道的合适钩子。JavaScript引擎调用构造函数,而不直接调用Angular。这就是创建ngOnInit(和AngularJS中的$ onInit)生命周期挂钩的原因。牢记这一点,存在使用构造函数的合适方案。这是我们要利用依赖注入的方法-本质上是为了将依赖“连接”到组件中。

当构造函数由JavaScript引擎初始化时,TypeScript允许我们告诉Angular我们需要针对特定​​属性映射哪些依赖项。

ngOnInit纯粹是为了向我们提供Angular已完成组件初始化的信号。

该阶段包括在变更检测中针对可能绑定到组件本身的属性进行的第一遍操作,例如使用@Input()装饰器。

因此,@ Input()属性在ngOnInit内部可用,但是在构造函数中,根据设计,它们是未定义的


2

构造函数是第一个,有时@input数据为null时会发生!因此我们使用Constructor进行声明服务,然后ngOnInit发生。构造器示例:

 constructor(translate: TranslateService, private oauthService: OAuthService) {
    translate.setDefaultLang('En');
        translate.use('En');}

onInit的示例:

ngOnInit() {
    this.items = [
      { label: 'A', icon: 'fa fa-home', routerLink: ['/'] },
      { label: 'B', icon: 'fa fa-home', routerLink: ['/'] }]
}

我认为onInit就像winForm中的InitialComponents()一样。


1

在Angular生命周期中

1)角注入器检测构造函数参数并实例化类。

2)下一个角度通话的生命周期

角生命周期挂钩

ngOnChanges->调用指令参数绑定。

ngOnInit->开始角度渲染...

以角度生命周期的状态调用其他方法。


1

constructor当Angular“实例化/构造”组件时,将调用。该ngOnInit方法是一个钩子,代表组件生命周期的初始化部分。一个好的做法是仅将其用于服务注入

constructor(private 
    service1: Service1,
    service2: Service2
){};

即使有可能,您也不应该在内部做一些“工作”。如果要启动某些在组件“初始化”时必须执行的操作,请使用ngOnInit

ngOnInit(){
    service1.someWork();
};

此外,涉及输入属性(来自父组件)的操作无法在构造器中完成。它们应该放在ngOnInit方法或另一个钩子中。与视图相关的元素(DOM)是相同的,例如viewchild元素

@Input itemFromParent: string;
@ViewChild('childView') childView;

constructor(){
    console.log(itemFromParent); // KO
    // childView is undefined here
};

ngOnInit(){
    console.log(itemFromParent); // OK
    // childView is undefined here, you can manipulate here
};

0

constructor() 用于进行依赖项注入。

ngOnInit()ngOnChanges()ngOnDestroy()等是生命周期方法。ngOnChanges()将是第一个被调用的对象,在之前ngOnInit(),当绑定属性的值更改时,如果没有更改,则不会调用它。ngOnDestroy()删除组件时调用。要使用它,OnDestroy需要implement由班级编辑。


1
同意,这很简短。例如,constructor()用于添加服务对象,ngOnInit()用于处理具有必要服务功能调用的组件。
史蒂夫(Steve

0

我找到了答案,然后尝试将其翻译成英语:即使在技术面试中,这个问题仍然出现。实际上,两者之间有很大的相似之处,但也存在一些差异。

  • 构造函数是ECMAScript的一部分。另一方面,ngOnInit()是角度的概念。

  • 即使不使用Angular,我们也可以在所有类中调用构造函数

  • LifeCycle:构造函数在ngOnInt()之前调用

  • 在构造函数中,我们不能调用HTML元素。但是,在ngOnInit()中可以。

  • 通常,服务调用在ngOnInit()中而不在构造函数中

    资料来源:http : //www.angular-tuto.com/Angular/Component#Diff


0

建设者

每个类都有构造函数,构造函数不是特定于Angular的,而是从面向对象设计派生的概念。构造函数创建组件类的实例。

初始化

ngOnInit函数是Angular组件的生命周期方法之一。Angular组件中的生命周期方法(或挂钩)使您可以在组件生命周期的不同阶段运行一段代码。与构造方法不同,ngOnInit方法来自OnInit组件需要实现才能使用此方法的Angular接口()。ngOnInit创建组件后不久将调用该方法。


0

当实例化该类时,将执行构造函数。它与角度无关。这是Javascript的功能,Angular无法对其进行控制

ngOnInit是Angular专用的,当Angular使用所有输入属性初始化组件时会调用ngOnInit

@Input属性在ngOnInit生命周期挂钩下可用。这将帮助您完成一些初始化工作,例如从后端服务器获取数据等以在视图中显示

@Input属性在构造函数中显示为未定义


-1

构造函数是在构建组件(或其他类)时执行的函数。

ngOnInit是属于组件生命周期方法组的函数,它们在组件的不同时刻执行(这就是为什么要命名生命周期)。这是所有这些的列表:

在此处输入图片说明 构造函数将在任何生命周期函数之前执行。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.