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

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


当前回答

为了测试这一点,我从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 ***  

其他回答

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

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

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

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

我认为最好的例子是使用服务。假设我想在我的组件“激活”时从我的服务器获取数据。假设我还想在从服务器获取数据后对数据做一些额外的处理,也许我得到了一个错误,想要以不同的方式记录它。

在构造函数上使用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();
    };


}

它使它更容易看到,所以当我初始化时,我只是在组件中调用我的函数而不是在其他地方寻找它。实际上,它只是另一个工具,可以让你在将来更容易阅读和使用。此外,我发现将函数调用放在构造函数中是非常糟糕的实践!

首先,ngOnInit是Angular生命周期的一部分,而constructor是ES6 JavaScript类的一部分,所以主要的区别就是从这里开始的!

请看下面我创建的图表,它展示了Angular的生命周期。

在Angular2+中,我们使用构造函数为我们做DI(依赖注入),而在Angular 1中,它是通过调用String方法并检查注入了哪个依赖。

正如你在上面的图表中看到的,ngOnInit是在构造函数准备好之后发生的,ngOnChnages和在组件为我们准备好之后被触发。所有的初始化都可以在这个阶段进行,一个简单的示例是注入一个服务并在init上初始化它。

好的,我还分享了一个示例代码给你看,看看我们如何在下面的代码中使用ngOnInit和构造函数:

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!');
  }
}

构造函数()可以接受参数并用于依赖注入,构造函数()用于添加服务对象。

构造函数在ngOnint()之前调用;

ngOnInit()用于用必要的服务函数调用操作组件,通常,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() 
   }
}

资源:生命周期钩子

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