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

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


当前回答

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

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

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

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

其他回答

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

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

引用自angular官方网站:

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

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

我将添加一个重要的东西,在上面的解释中被跳过,并解释什么时候你必须使用ngOnInit。

如果你通过ViewChildren, ContentChildren或ElementRef对组件的DOM进行任何操作,你的原生元素在构造函数阶段将不可用。

然而,由于ngOnInit发生在组件被创建和检查(ngOnChanges)被调用之后,你可以在这一点上访问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
  }
}

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

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


}

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

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

我找到了答案,试着把它翻译成英语: 即使在技术面试中,这个问题仍然会出现。事实上,两者之间有很大的相似之处,但也有一些不同。

构造函数是ECMAScript的一部分。另一方面,ngOnInit()是angular的概念。 即使不使用Angular,我们也可以在所有类中调用构造函数 生命周期:构造函数在ngOnInt()之前调用 在构造函数中,我们不能调用HTML元素。然而,在ngOnInit()中我们可以。 通常,服务调用在ngOnInit()中,而不是在构造函数中 来源:http://www.angular-tuto.com/Angular/Component Diff