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

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


当前回答

构造函数在类实例化时执行。它与棱角无关。这是Javascript的特性,Angular无法控制它

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

@Input属性在ngOnInit生命周期钩子下可用。这将帮助你做一些初始化的事情,比如从后端服务器获取数据等显示在视图中

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

其他回答

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

user.ts

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

第一个(构造函数)与类实例化有关,与Angular2无关。构造函数可以用在任何类上。您可以在其中放入一些新创建实例的初始化处理。

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

引用自angular官方网站:

当输入或输出绑定值发生变化时调用ngOnChanges 在第一个ngOnChanges之后调用ngOnInit

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

构造函数: ES6类(这里是TypeScript)的构造函数方法是类本身的特性,而不是Angular的特性。当调用构造函数时,它不在Angular的控制范围内,这意味着它不是一个合适的钩子来告诉你Angular何时完成了组件的初始化。JavaScript引擎调用构造函数,而不是直接调用Angular。这就是为什么创建了ngOnInit(和AngularJS中的$onInit)生命周期钩子。记住这一点,有一个使用构造函数的合适场景。这就是我们想要利用依赖注入的时候——本质上是为了将依赖“连接”到组件中。

由于构造函数是由JavaScript引擎初始化的,TypeScript允许我们告诉Angular,我们需要将哪些依赖关系映射到特定的属性上。

ngOnInit只是给我们一个信号,表明Angular已经完成了组件的初始化。

这个阶段包括针对我们可能绑定到组件本身的属性的Change Detection的第一步——比如使用@Input()装饰器。

因此,@Input()属性在ngOnInit中是可用的,但是在构造函数中是未定义的

简短而简单的回答是,

构造函数:构造函数是在构造组件时(默认情况下)运行的默认方法。当创建类的实例时,也会调用构造函数(默认方法)。换句话说,当构建组件或/和创建实例时,调用构造函数(默认方法)并调用其中编写的相关代码。基本上,在Angular2中,当组件被构造以供进一步使用时,它被用来注入服务之类的东西。

OnInit: ngOnInit是组件的生命周期钩子,当组件初始化时,它首先在构造函数(默认方法)之后运行。

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

boot.ts

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() 
   }
}

资源:生命周期钩子

你可以查看这个小演示,它展示了这两件事的实现。

构造函数是第一个执行的,当@input data为空时有时会发生这种情况! 所以我们使用构造函数注入服务,ngOnInit在后面发生。 构造函数示例:

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

示例ngOnInit:

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

我认为ngOnInit就像winForm中的InitialComponents()。