Diferencia entre Constructor y ngOnInit

Angular proporciona el ngOnInit ciclo de vida ngOnInit por defecto.

¿Por qué se debería ngOnInit , si ya tenemos un constructor ?

El Constructor es un método predeterminado de la clase que se ejecuta cuando se crea una instancia de la clase y garantiza la inicialización adecuada de los campos en la clase y sus subclases. Angular o mejor Dependency Injector (DI) analiza los parámetros del constructor y cuando crea una nueva instancia llamando a la new MyClass() intenta encontrar proveedores que coincidan con los tipos de parámetros del constructor, los resuelve y los pasa al constructor como

 new MyClass(someArg); 

ngOnInit es un gancho de ciclo de vida llamado por Angular2 para indicar que Angular ha terminado de crear el componente.

Tenemos que importar OnInit para utilizarlo de esta manera (en realidad, la implementación de OnInit no es obligatoria, pero se considera una buena práctica):

 import {Component, OnInit} from '@angular/core'; 

luego para usar el método de OnInit tenemos que implementar en la clase de esta manera.

 export class App implements OnInit{ constructor(){ //called first time before the ngOnInit() } ngOnInit(){ //called after the constructor and called after the first ngOnChanges() } } 

Implemente esta interfaz para ejecutar una lógica de inicialización personalizada después de que se hayan inicializado las propiedades vinculadas a datos de su directiva. ngOnInit se invoca justo después de que se hayan verificado las propiedades ligadas a datos de la directiva por primera vez, y antes de que se haya verificado cualquiera de sus elementos secundarios. Se invoca solo una vez cuando se crea una instancia de la directiva.

Sobre todo usamos ngOnInit para toda la inicialización / statement y evitamos que cosas funcionen en el constructor. El constructor solo debe usarse para inicializar los miembros de la clase, pero no debe hacer un “trabajo” real.

Entonces debería usar constructor() para configurar Inyección de Dependencia y no mucho más. ngOnInit () es el mejor lugar para “comenzar”: es donde / cuando se resuelven los enlaces de los componentes.

Para obtener más información, consulte aquí:

Creo que el mejor ejemplo sería usar servicios. Digamos que quiero tomar datos de mi servidor cuando mi componente se ‘Activa’. Digamos que también quiero hacer algunas cosas adicionales con los datos después de obtenerlos del servidor, tal vez me da un error y quiero registrarlo de manera diferente.

Es realmente fácil con ngOnInit sobre un constructor, también limita cuántas capas de callback necesito agregar a mi aplicación.

Por ejemplo:

 export class Users implements OnInit{ user_list: Array; constructor(private _userService: UserService){ }; ngOnInit(){ this.getUsers(); }; getUsers(){ this._userService.getUsersFromService().subscribe(users => this.user_list = users); }; } 

con mi constructor podría simplemente llamar a mi _userService y completar mi lista de usuarios, pero tal vez quiera hacer algunas cosas adicionales con ella. Al igual que asegúrese de que todo esté en mayúsculas, no estoy del todo seguro de cómo están llegando mis datos.

Por lo tanto, es mucho más fácil usar ngOnInit.

 export class Users implements OnInit{ user_list: Array; constructor(private _userService: UserService){ }; ngOnInit(){ this.getUsers(); }; getUsers(){ this._userService.getUsersFromService().subscribe(users => this.user_list = users); this.user_list.toUpperCase(); }; } 

Hace que sea mucho más fácil de ver, así que solo llamo a mi función dentro de mi componente cuando lo inicializo en lugar de tener que buscarlo en otro lugar. Realmente es solo otra herramienta que puede usar para facilitar la lectura y el uso en el futuro. ¡También me parece una mala práctica poner llamadas a funciones dentro de un constructor!

El artículo La diferencia esencial entre Constructor y ngOnInit en Angular explora la diferencia desde múltiples perspectivas. Esta respuesta proporciona la explicación de la diferencia más importante relacionada con el proceso de inicialización del componente que también muestra el diferente uso.

El proceso de arranque angular consiste en las dos etapas principales:

  • construyendo un árbol de componentes
  • detección de cambio de funcionamiento

El constructor del componente se llama cuando Angular construye el árbol de componentes. Todos los enganches de ciclo de vida se llaman como parte de la detección de cambio de funcionamiento.

Cuando Angular construye el árbol de componentes, el inyector del módulo raíz ya está configurado para que pueda inyectar dependencias globales. Además, cuando Angular crea una instancia de una clase de componente secundario, el inyector para el componente principal también está configurado para que pueda inyectar proveedores definidos en el componente principal, incluido el componente principal. Los constructores de componentes son el único método que se llama en el contexto del inyector, por lo que si necesita alguna dependencia es el único lugar para obtener esas dependencias.

Cuando Angular inicia la detección de cambios, se construye el árbol de componentes y se invocan los constructores para todos los componentes del árbol. Además, los nodos de plantilla de cada componente se agregan al DOM. El mecanismo de comunicación @Input se procesa durante la detección de cambios, por lo que no puede esperar tener las propiedades disponibles en el constructor. Estará disponible después de ngOnInit .

Veamos un ejemplo rápido. Supongamos que tiene la siguiente plantilla:

   

Entonces Angular comienza a arrancar la aplicación. Como dije, primero crea clases para cada componente. Por lo tanto, llama MyAppComponent constructor MyAppComponent . También crea un nodo DOM que es el elemento host del componente my-app . A continuación, se procede a crear un elemento de host para el child-comp y para llamar ChildComponent constructor ChildComponent . En esta etapa, no está realmente preocupado por el enlace de entrada i y los ganchos de ciclo de vida. Entonces, cuando este proceso finaliza, Angular termina con el siguiente árbol de vistas de componentes:

 MyAppView - MyApp component instance - my-app host element data ChildCompnentView - ChildComponent component instance - child-comp host element data 

Solo entonces se ejecuta la detección de cambios y los enlaces de actualizaciones para my-app y se llama a ngOnInit en la clase MyAppComponent. Luego procede a actualizar los enlaces para child-comp y llama a ngOnInit en la clase ChildComponent.

Puedes hacer tu lógica de inicialización en constructor o ngOnInit dependiendo de lo que necesites. Por ejemplo, el artículo Aquí se muestra cómo obtener ViewContainerRef antes de que se evalúe la consulta de @ViewChild muestra qué tipo de lógica de inicialización se puede requerir que se realice en el constructor.

Aquí hay algunos artículos que lo ayudarán a comprender mejor el tema:

  • Todo lo que necesita saber sobre detección de cambios en Angular
  • El $ digest de Angular renace en la versión más nueva de Angular
  • La mecánica de los enlaces de propiedad se actualiza en Angular

El primero (constructor) está relacionado con la instanciación de clase y no tiene nada que ver con Angular2. Quiero decir que un constructor se puede usar en cualquier clase. Puede ponerle algún proceso de inicialización para la instancia recién creada.

El segundo corresponde a un gancho de ciclo de vida de componentes Angular2:

Citado del sitio web oficial de angular:

  • ngOnChanges se ngOnChanges cuando cambia un valor de enlace de entrada o salida
  • ngOnInit se llama después de los primeros ngOnChanges

Por lo tanto, debe usar ngOnInit si el proceso de inicialización depende de los enlaces del componente (por ejemplo, los parámetros de los componentes definidos con @Input ); de lo contrario, el constructor sería suficiente …

OK, en primer lugar ngOnInit es parte del ciclo de vida angular , mientras que el constructor es parte de la clase de JavaScript ES6 , ¡así que la diferencia principal comienza aquí! …

Mira el siguiente gráfico que creé que muestra el ciclo de vida de Angular.

ngOnInit vs constructor

En Angular2 + usamos constructor para hacer la DI(Dependency Injection) para nosotros, mientras que en Angular 1 estaba sucediendo al llamar al método String y verificar qué dependencia se inyectó.

Como puede ver en el diagtwig anterior, ngOnInit está sucediendo después de que el constructor esté listo y ngOnChnages y se ngOnChnages después de que el componente esté listo para nosotros. Toda la inicialización puede ocurrir en esta etapa, una muestra simple está inyectando un servicio y lo inicializa en init.

OK, también comparto un código de muestra para que lo veas, mira cómo usamos ngOnInit y el constructor en el siguiente código:

 import { Component, OnInit } from '@angular/core'; import { Router } from '@angular/router'; @Component({ selector: 'my-app', template: `

App is running!

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

Una respuesta corta y simple sería,

Constructor : constructor es un default method ejecuta ( por deafult ) cuando se está construyendo el componente. Cuando creas an instance de una clase, esa vez también se llamará al constructor(default method) . En otras palabras, cuando el componente se está constructed or/and an instance is created constructor(default method) se llama al código relevante escrito dentro de él. Básicamente y en general en Angular2 solía inyectar cosas como services cuando el componente se está construyendo para su uso posterior.

OnInit : ngOnInit es el enlace del ciclo de vida del componente que se ejecuta primero después del constructor(default method) cuando el componente se está inicializando.

Entonces, se llamará primero a su constructor y se llamará a Oninit más tarde después del método de constructor.

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

Recursos: gancho LifeCycle

Puede verificar esta pequeña demostración que muestra la implementación de ambas cosas.

Para probar esto, escribí este código, tomando prestado del tutorial de NativeScript :

usuario.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; } } 

Salida de consola

 JS: *** User class constructor property *** JS: *** User class constructor constructor *** JS: *** Login Component Constructor *** JS: *** User class constructor ngOnInit *** JS: *** Login Component ngOnInit *** 

ngOnInit una cosa importante que se saltó en las explicaciones anteriores y explica cuándo DEBE usar ngOnInit .

Si está realizando alguna manipulación del DOM del componente vía, por ejemplo, ViewChildren , ContentChildren o ElementRef , sus elementos nativos no estarán disponibles durante la fase de construcción.

Sin embargo, dado que ngOnInit ocurre una vez que se ha creado el componente y se han llamado las comprobaciones ( ngOnChanges ), puede acceder al DOM en este punto.

 export class App implements OnInit { @ViewChild('myTemplate') myTemplate: TemplateRef; constructor(private elementRef: ElementRef) { // this.elementRef.nativeElement is undefined here // this.myTemplate is undefined here } ngOnInit() { // this.elementRef.nativeElement can be used from here on // this.myTemplate can be used from here on } } 

Las respuestas anteriores no responden realmente a este aspecto de la pregunta original: ¿Qué es un gancho de ciclo de vida? Me tomó un tiempo entender lo que eso significa hasta que lo pensé de esta manera.

1) Diga que su componente es un ser humano. Los seres humanos tienen vidas que incluyen muchas etapas de la vida, y luego expiramos.

2) Nuestro componente humano podría tener el siguiente guión del ciclo de vida: Nacido, Bebé, Escuela primaria, Adulto joven, Adulto de mediana edad, Adulto mayor, Muerto, Dispuesto de.

3) Di que quieres tener una función para crear niños. Para evitar que esto se vuelva complicado, y más bien gracioso, desea que su función solo se llame durante la etapa de Adulto Joven de la vida de los componentes humanos. Entonces usted desarrolla un componente que solo está activo cuando el componente padre se encuentra en la etapa de Adulto Joven. Los ganchos te ayudan a hacer eso al señalar esa etapa de la vida y dejar que tu componente actúe en consecuencia.

Cosas divertidas. Si dejas que tu imaginación llegue a codificar algo así, se vuelve complicado y divertido.

Al igual que muchos otros lenguajes, puede inicializar variables en el nivel de clase, el constructor o un método. Depende del desarrollador decidir qué es lo mejor en su caso particular. Pero a continuación hay una lista de mejores prácticas a la hora de decidir.

Variables de nivel de clase

Generalmente, declarará aquí todas sus variables que se usarán en el rest de su componente. Puede inicializarlos si el valor no depende de nada más, o usar la palabra clave const para crear constantes si no cambian.

 export class TestClass{ let varA: string = "hello"; } 

Constructor

Normalmente, es una buena práctica no hacer nada en el constructor y simplemente usarlo para las clases que se inyectarán. La mayoría de las veces su constructor debería verse así:

  constructor(private http: Http, private customService: CustomService) {} 

esto creará automáticamente las variables de nivel de clase, por lo que tendrá acceso a customService.myMethod() sin tener que hacerlo manualmente.

NgOnInit

NgOnit es un gancho de ciclo de vida proporcionado por el marco Angular 2. Su componente debe implementar OnInit para poder usarlo. Se llama a este gancho de ciclo de vida después de que se llama al constructor y se inicializan todas las variables. La mayor parte de tu inicialización debería ir aquí. Tendrás la certeza de que Angular ha inicializado correctamente tu componente y puedes comenzar a hacer cualquier lógica que necesites en OnInit versus hacer cosas cuando tu componente no haya terminado de cargarse correctamente.

Aquí hay una imagen que detalla el orden de lo que se llama:

enter image description here

https://angular.io/docs/ts/latest/guide/lifecycle-hooks.html

TLDR

Si está utilizando el marco Angular 2 y necesita interactuar con ciertos eventos del ciclo de vida, use los métodos provistos por el marco para evitar problemas.

La principal diferencia entre el constructor y ngOnInit es que ngOnInit es el ciclo de vida y se ejecuta después del constructor. La plantilla interpolada por componentes y los valores iniciales de entrada no están disponibles en el constructor, pero están disponibles en ngOnInit .

La diferencia práctica es cómo ngOnInit afecta cómo se estructura el código. La mayoría del código de inicialización se puede mover a ngOnInit , siempre que esto no cree condiciones de carrera .

Constructor antipattern

Una cantidad sustancial de código de inicialización hace que el método constructor sea difícil de extender, leer y probar.

Una receta habitual para separar la lógica de inicialización del constructor de clase es moverla a otro método como init :

 class Some { constructor() { this.init(); } init() {...} } 

ngOnInit puede servir para este propósito en componentes y directivas:

 constructor( public foo: Foo, /* verbose list of dependencies */ ) { // time-sensitive initialization code this.bar = foo.getBar(); } ngOnInit() { // rest of initialization code } 

Inyección de dependencia

La función principal de los constructores de clase en Angular es la dependency injection. Los constructores también se utilizan para la anotación DI en TypeScript. Casi todas las dependencias se asignan como propiedades a la instancia de la clase.

El constructor promedio de componentes / directivas ya es lo suficientemente grande porque puede tener una firma de líneas múltiples debido a las dependencias, lo que hace que la lógica de inicialización innecesaria para el cuerpo constructor contribuya al antipatrón.

Inicialización asincrónica

El constructor de inicialización asíncrono a menudo se puede considerar como antipattern y tiene olor porque la creación de instancias de clase finaliza antes que la rutina asincrónica, y esto puede crear condiciones de carrera. Si no es el caso, ngOnInit y otros ganchos de ciclo de vida son mejores lugares para esto, particularmente porque pueden beneficiarse de la syntax async :

 constructor( public foo: Foo, public errorHandler: ErrorHandler ) {} async ngOnInit() { try { await this.foo.getBar(); await this.foo.getBazThatDependsOnBar(); } catch (err) { this.errorHandler.handleError(err); } } 

Si hay condiciones de carrera (incluida la de que un componente no debería aparecer en el error de inicialización), la rutina de inicialización asíncrona debe tener lugar antes de la instanciación del componente y debe moverse al componente principal, al protector del enrutador, etc.

Examen de la unidad

ngOnInit es más flexible que un constructor y proporciona algunos beneficios para las pruebas unitarias que se explican en detalle en esta respuesta .

Teniendo en cuenta que ngOnInit no se ngOnInit automáticamente en la comstackción de componentes en pruebas unitarias, los métodos que se ngOnInit en ngOnInit se pueden espiar o burlar después de la ngOnInit instancias de componentes.

En casos excepcionales, ngOnInit puede suprimirse por completo para proporcionar aislamiento a otras unidades componentes (por ejemplo, cierta lógica de plantilla).

Herencia

Las clases secundarias solo pueden boost constructores, no reemplazarlos.

Como this no se puede referir antes de super() , esto impone restricciones a la precedencia de inicialización.

Teniendo en cuenta que Angular component o directive usa ngOnInit para la lógica de inicialización insensible al tiempo, las clases secundarias pueden elegir si se llama a super.ngOnInit() y cuándo:

 ngOnInit() { this.someMethod(); super.ngOnInit(); } 

Esto sería imposible de implementar solo con el constructor.

Constructores Angulares 2: –

  1. El constructor es un método predeterminado que se ejecuta cuando se está construyendo el componente.
  2. El constructor es una característica de mecanografía y se usa solo para instancias de clase y nada que ver con Angular 2.
  3. El constructor llamó por primera vez antes de ngOnInit ().

Angular 2 ngOnInit: –

  1. El evento ngOnInit es un método de evento de ciclo de vida angular 2 que se invoca después de los primeros ngOnChanges y el método ngOnInit se usa para parámetros definidos con @Input; de lo contrario, el constructor está bien.

  2. El ngOnInit se invoca después del constructor y se invoca ngOnInit después del primer ngOnChanges.

  3. Se invoca ngOnChanges cuando cambia un valor de enlace de entrada o salida.

El siguiente diagtwig explica el ciclo de mentira de Angular. De eso puedes obtener una idea sobre el orden en que se llama a cada uno.

enter image description here

El constructor es un método en JavaScript y se considera como una característica de la clase en es6. Cuando se crea una instancia de la clase, inmediatamente ejecuta el constructor, ya sea que se use en el marco angular o no. Así es invocado por el motor de JavaScript y Angular no tiene control sobre eso.

 import {Component} from '@angular/core'; @Component({}) class CONSTRUCTORTEST { //This is called by Javascript not the Angular. constructor(){ console.log("view constructor initialised"); } } 

La clase “ConstructorTest” se instancia a continuación, por lo que internamente llama al constructor (Todo esto sucede mediante JavaScript (es6) no Angular).

 new CONSTRUCTORTEST(); 

Es por eso que hay gancho del ciclo de vida ngOnInit en Angular.ngOnInit representa cuando Angular ha terminado de inicializar el componente.

 import {Component} from '@angular/core'; @Component({}) class NGONINITTEST implements onInit{ constructor(){} //ngOnInit calls by Angular ngOnInit(){ console.log("Testing ngOnInit"); } } 

Primero instanciamos la clase de la siguiente manera, que ocurre con las ejecuciones inmediatas del método constructor.

 let instance = new NGONINITTEST(); 

ngOnInit es llamado por Angular cuando es necesario, como se muestra a continuación:

 instance.ngOnInit(); 

¿Pero puede preguntar por qué estamos usando constructor en Angular?

La respuesta es inyecciones de dependencias . Como se mencionó anteriormente, el constructor llama por el motor de JavaScript inmediatamente cuando se crea una instancia de la clase (antes de llamar a ngOnInit por Angular), mecanografía nos ayuda a obtener el tipo de dependencias definidas en el constructor y finalmente nos dice Angular qué tipo de dependencias queremos usar en ese componente específico.

Dos cosas para observar aquí:

  1. Se llama al constructor cada vez que se crea un objeto de esa clase.
  2. ngOnInit llamado una vez que se crea el componente.

Ambos tienen diferente usabilidad.

Ambos métodos tienen diferentes objectives / responsabilidades. La tarea del constructor (que es una característica admitida por el lenguaje) es asegurarse de que la representación invariante se mantenga. De lo contrario, asegúrate de que la instancia sea válida dando los valores correctos a los miembros. Depende del desarrollador decidir qué significa “correcto”.

La tarea del método onInit () (que es un concepto angular) es permitir invocaciones de método en un objeto correcto (representación invariante). Cada método debe a su vez asegurarse de que la representación invariante se mantenga cuando el método finaliza.

El constructor se debe usar para crear objetos ‘correctos’, el método onInit le da la oportunidad de invocar llamadas a métodos en una instancia bien definida.

Constructor: el método constructor en una clase ES6 (o TypeScript en este caso) es una característica de una clase en sí misma, en lugar de una característica angular. Está fuera del control de Angular cuando se invoca el constructor, lo que significa que no es un gancho adecuado para avisarte cuando Angular ha terminado de inicializar el componente. El motor de JavaScript llama al constructor, no a Angular directamente. Por eso se creó el gancho del ciclo de vida ngOnInit (y $ onInit en AngularJS). Teniendo esto en cuenta, hay un escenario adecuado para usar el constructor. Esto es cuando queremos utilizar la dependency injection, esencialmente para “conectar” dependencias en el componente.

A medida que el motor de JavaScript inicializa el constructor, TypeScript nos permite decirle a Angular qué dependencias necesitamos para mapear contra una propiedad específica.

ngOnInit está puramente ahí para darnos una señal de que Angular ha terminado de inicializar el componente.

Esta fase incluye la primera pasada en Change Detection contra las propiedades que podemos vincular al componente en sí, como el uso de un decorador @Input ().

Debido a esto, las propiedades @Input () están disponibles dentro de ngOnInit, sin embargo, están indefinidas dentro del constructor, por diseño

constructor () es el método predeterminado en el ciclo de vida del componente y se utiliza para la dependency injections. Constructor es una característica de TypeScript.

Se llama a ngOnInit () después de llamar al constructor y ngOnInit después de los primeros ngOnChanges.

es decir, Constructor () -> ngOnChanges () -> ngOnInit ()

como se mencionó anteriormente, ngOnChanges () se invoca cuando cambia un valor de enlace de entrada o salida.

constructor() se usa para hacer dependency injection.

ngOnInit() , ngOnChanges() y ngOnDestroy() etc. son métodos de ciclo de vida. ngOnChanges() será el primero en ser llamado, antes de que ngOnInit() , cuando el valor de una propiedad vinculada cambie, NO se ngOnInit() si no hay cambios. ngOnDestroy() se ngOnDestroy() cuando se elimina el componente. Para usarlo, OnDestroy necesita ser implement por la clase.

En los ciclos de vida angulares

1) El inyector angular detecta los parámetros del constructor (‘s) y crea una instancia de la clase.

2) Próximo ciclo de vida de llamada angular

Angular Lifecycle Hooks

ngOnChanges -> Llamada en el enlace de los parámetros de la directiva.

ngOnInit -> Comenzar procesamiento angular …

Llame a otro método con estado de ciclo de vida angular.