构造函数和ngOnInit之间的区别

角度的 TypeScript

Mandy

2020-05-25

Angular ngOnInit默认提供生命周期挂钩

ngOnInit如果已经有了,为什么要使用constructor

第4170篇《构造函数和ngOnInit之间的区别》来自Winter(https://github.com/aiyld/aiyld.github.io)的站点

17个回答
斯丁前端 2020.05.25

为了测试这一点,我编写了以下代码,借鉴了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 ***  
古一 2020.05.25

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

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

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

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

宝儿理查德 2020.05.25

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

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

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

达蒙小小 2020.05.25

的 

@Input

 通信机制是作为后续更改检测阶段的一部分进行处理的,因此输入绑定在构造函数中不可用。

樱小胖Mandy 2020.05.25

建设者

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

初始化

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

神离 2020.05.25

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

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

番长樱梅 2020.05.25

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

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

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

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

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

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

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

伽罗 2020.05.25

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

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

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

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

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

小小仲羽 2020.05.25

这里要注意两件事:

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

两者都有不同的可用性。

Stafan 2020.05.25

在Angular生命周期中

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

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

角生命周期挂钩

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

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

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

Tony凯 2020.05.25

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

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

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

2020.05.25

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

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

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

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

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

阿飞 2020.05.25

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

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

即:

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

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

飞羽宝儿 2020.05.25

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

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

从Angular官方网站引用:

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

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

三千曜 2020.05.25

我只会添加一个在上面的说明中跳过的重要事项,并说明您必须使用的时间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
  }
}
番长樱梅 2020.05.25

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

类级变量

通常,您将在此处声明所有变量,这些变量将在其余组件中使用。如果值不依赖其他任何内容,则可以对其进行初始化;如果它们不变,则可以使用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框架,并且需要与某些生命周期事件进行交互,请使用该框架提供的方法来避免问题。

伊芙妮 2020.05.25

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

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


}

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

问题类别

JavaScript Ckeditor Python Webpack TypeScript Vue.js React.js ExpressJS KoaJS CSS Node.js HTML Django 单元测试 PHP Asp.net jQuery Bootstrap IOS Android