Angular默认提供了生命周期钩子ngOnInit。

为什么要使用ngOnInit,如果我们已经有一个构造函数?


当前回答

构造函数是JavaScript中的一个方法,在es6中被认为是类的一个特性。当类被实例化时,无论是否在Angular框架中使用,它都会立即运行构造函数。所以它是由JavaScript引擎调用的,Angular对此没有控制。

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)实现的,而不是Angular)。

new CONSTRUCTORTEST();

这就是为什么Angular中有ngOnInit生命周期钩子。ngOnInit在Angular完成组件初始化后才会呈现。

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中使用构造函数?

答案是依赖注入。正如前面提到的,当类被实例化时(在Angular调用ngOnInit之前),JavaScript引擎会立即调用构造函数,因此typescript帮助我们获得在构造函数中定义的依赖类型,并最终告诉Angular我们想在特定组件中使用什么类型的依赖。

其他回答

像许多其他语言一样,可以在类级、构造函数或方法上初始化变量。这取决于开发人员来决定在他们的特定情况下什么是最好的。但下面是在做决定时的最佳实践清单。

类级变量

通常,您将在这里声明将在组件的其余部分中使用的所有变量。如果值不依赖于其他任何东西,可以初始化它们,或者如果它们不会改变,则使用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框架,并且需要与特定的生命周期事件交互,请使用框架提供的方法来避免问题。

构造函数是类的默认方法,在类实例化时执行,并确保类及其子类中的字段正确初始化。Angular,或者更好的依赖注入器(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进行所有的初始化/声明,避免在构造函数中工作。构造函数应该只用于初始化类成员,而不应该做实际的“工作”。

因此,您应该使用构造函数()来设置依赖注入,而不是其他什么。ngOnInit()是更好的“开始”的地方——它是解析组件绑定的地方。

更多信息请参考这里:

https://angular.io/api/core/OnInit Angular组件构造函数Vs OnInit

需要注意的是,@Input值在构造函数中是不可访问的(感谢@tim在注释中提出的建议)

构造函数是ES6的一部分,typescript使用ES6语法,现在也使用es7语法,所以你可以利用typescript将编译为es5/es4(根据你的定义)的高级功能来提供对旧浏览器的支持。

而ngOnInIt是angular的生命周期钩子。当你的组件被初始化时,它也被初始化。(把它的状态看作是新生的状态)

使用ngOnInIt比较构造函数是明智的,因为你有另一个生命周期钩子,如ngOnDestory(认为它是任何生命的死亡)。在这里,你可以取消订阅任何可观察对象,这有助于防止任何内存泄漏。

如果有任何问题,请随意评论这个答案。

构造函数

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

OnInit

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

构造函数是JavaScript中的一个方法,在es6中被认为是类的一个特性。当类被实例化时,无论是否在Angular框架中使用,它都会立即运行构造函数。所以它是由JavaScript引擎调用的,Angular对此没有控制。

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)实现的,而不是Angular)。

new CONSTRUCTORTEST();

这就是为什么Angular中有ngOnInit生命周期钩子。ngOnInit在Angular完成组件初始化后才会呈现。

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中使用构造函数?

答案是依赖注入。正如前面提到的,当类被实例化时(在Angular调用ngOnInit之前),JavaScript引擎会立即调用构造函数,因此typescript帮助我们获得在构造函数中定义的依赖类型,并最终告诉Angular我们想在特定组件中使用什么类型的依赖。