Perbedaan antara konstruktor dan ngOnInit

Jawaban:

1112

Ini Constructoradalah metode default kelas yang dieksekusi ketika kelas instantiated dan memastikan inisialisasi bidang dalam kelas dan subkelasnya. Angular, atau Dependency Injector (DI) yang lebih baik, menganalisis parameter konstruktor dan ketika ia membuat instance baru dengan memanggilnya new MyClass()mencoba menemukan penyedia yang cocok dengan jenis parameter konstruktor, menyelesaikannya dan meneruskannya ke konstruktor seperti

new MyClass(someArg);

ngOnInit adalah pengait siklus hidup yang disebut oleh Angular untuk menunjukkan bahwa Angular telah selesai membuat komponen.

Kita harus mengimpor OnInitseperti ini untuk menggunakannya (sebenarnya implementasi OnInittidak wajib tetapi dianggap praktik yang baik):

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

kemudian untuk menggunakan make us of the method OnInit, kita harus mengimplementasikan kelas seperti ini:

export class App implements OnInit {
  constructor() {
     // Called first time before the ngOnInit()
  }

  ngOnInit() {
     // Called after the constructor and called  after the first ngOnChanges() 
  }
}

Terapkan antarmuka ini untuk menjalankan logika inisialisasi kustom setelah properti terikat data direktif Anda telah diinisialisasi. ngOnInit dipanggil tepat setelah properti data-terikat direktif telah diperiksa untuk pertama kalinya, dan sebelum anak-anaknya diperiksa. Itu dipanggil hanya sekali ketika direktif dipakai.

Sebagian besar kami gunakan ngOnInituntuk semua inisialisasi / deklarasi dan menghindari hal-hal untuk bekerja di konstruktor. Konstruktor seharusnya hanya digunakan untuk menginisialisasi anggota kelas tetapi seharusnya tidak melakukan "pekerjaan" yang sebenarnya.

Jadi, Anda harus menggunakan constructor()untuk mengatur Injeksi Ketergantungan dan tidak banyak lagi. ngOnInit () adalah tempat yang lebih baik untuk "memulai" - ini adalah di mana / ketika binding komponen diselesaikan.

Untuk informasi lebih lanjut lihat di sini:

Pardeep Jain
sumber
62
Tepatnya, sebagian besar (atau bahkan semua) bahasa berbasis kelas memiliki konstruktor untuk memastikan urutan inisialisasi yang tepat terutama dari kelas yang memperluas kelas lain di mana beberapa masalah yang cukup sulit dapat muncul, seperti bidang terakhir (tidak tahu apakah TS memilikinya) dan sejenisnya. Konstruktor tidak terkait dengan Angular2, mereka adalah fitur TypeScript. Kait siklus hidup dipanggil oleh Angular setelah beberapa inisialisasi terjadi atau ketika beberapa peristiwa dengan senang hati mengizinkan komponen bertindak pada situasi tertentu dan memberikannya kesempatan untuk melakukan beberapa tugas pada waktu yang tepat.
Günter Zöchbauer
13
Ada kutipan blok di angular.io/docs/ts/latest/guide/server-communication.html yang juga menjelaskan ini: "Komponen lebih mudah untuk diuji dan di-debug ketika konstruktornya sederhana, dan semua pekerjaan nyata (terutama memanggil server jauh) ditangani dalam metode terpisah. " - Dalam hal ini metode itu adalah ngOnInit ()
yoonjesung
3
adalah pengait siklus hidup yang disebut oleh Angular2 untuk menunjukkan bahwa Angular telah selesai membuat komponen. - bukan itu. itu menandakan bahwa itu menginisialisasi binding. Komponen dibuat sebelumnya. Lihat jawaban saya
Max Koretskyi
22
Seperti dengan semua "praktik terbaik", saya pikir itu akan menjadi ide yang baik untuk juga menjelaskan mengapa Anda tidak boleh melakukan "pekerjaan" di konstruktor. Artikel ini oleh ketua tim Angular padat tetapi dapat membantu: misko.hevery.com/code-reviewers-guide/… Juga, kurang penting harus ditempatkan pada mantra yang diperlukan untuk mengimplementasikan OnInit (ini mudah ditemukan) dan lebih lanjut tentang fakta penting bahwa binding data tidak tersedia di konstruktor.
Reikim
2
Jika mode ketat benar dalam tsconfig.jsonfile seperti "strict": true, maka Anda harus menginisialisasi anggota kelas di constructor, bukan di ngOnitsuka FormGroup.
Rohit Sharma
174

Artikel Perbedaan mendasar antara Konstruktor dan ngOnInit di Angular mengeksplorasi perbedaan dari berbagai perspektif. Jawaban ini memberikan penjelasan perbedaan paling penting terkait dengan proses inisialisasi komponen yang juga menunjukkan perbedaan dalam penggunaan.

Proses bootstrap sudut terdiri dari dua tahap utama:

  • membangun komponen pohon
  • menjalankan deteksi perubahan

Konstruktor komponen dipanggil ketika Angular membangun komponen tree. Semua kait siklus hidup disebut sebagai bagian dari menjalankan deteksi perubahan.

Ketika Angular membangun komponen tree, injektor modul root sudah dikonfigurasi sehingga Anda dapat menyuntikkan dependensi global. Juga, ketika Angular membuat instance kelas komponen anak, injektor untuk komponen induk juga sudah disiapkan sehingga Anda dapat menyuntikkan penyedia yang ditentukan pada komponen induk termasuk komponen induk itu sendiri. Konstruktor komponen adalah satu-satunya metode yang disebut dalam konteks injector jadi jika Anda memerlukan dependensi itulah satu-satunya tempat untuk mendapatkan dependensi tersebut.

Ketika sudut mulai mengubah deteksi komponen pohon dibangun dan konstruktor untuk semua komponen di pohon telah dipanggil. Juga setiap templat templat komponen ditambahkan ke DOM. The @Inputmekanisme komunikasi diproses selama deteksi perubahan sehingga Anda tidak bisa berharap untuk memiliki properti yang tersedia dalam konstruktor. Ini akan tersedia setelah ngOnInit.

Mari kita lihat contoh singkatnya. Misalkan Anda memiliki templat berikut:

<my-app>
   <child-comp [i]='prop'>

Jadi Angular mulai mem-bootstrap aplikasi. Seperti yang saya katakan pertama kali membuat kelas untuk setiap komponen. Jadi itu disebut MyAppComponentkonstruktor. Ini juga menciptakan simpul DOM yang merupakan elemen host dari my-appkomponen. Kemudian mulai membuat elemen host untuk child-compdan memanggil ChildComponentkonstruktor. Pada tahap ini tidak terlalu peduli dengan ipengikatan input dan pengait siklus hidup. Jadi ketika proses ini selesai, Angular berakhir dengan susunan tampilan komponen berikut:

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

Hanya kemudian menjalankan deteksi perubahan dan memperbarui binding untuk my-appdan panggilan ngOnInitdi kelas MyAppComponent. Kemudian mulai memperbarui binding untuk child-compdan memanggil ngOnInitkelas ChildComponent.

Anda dapat melakukan logika inisialisasi Anda di konstruktor atau ngOnInittergantung pada apa yang Anda butuhkan tersedia. Sebagai contoh artikel di sini adalah cara mendapatkan ViewContainerRef sebelum permintaan @ViewChild dievaluasi menunjukkan apa jenis logika inisialisasi yang diperlukan untuk dilakukan di konstruktor.

Berikut beberapa artikel yang akan membantu Anda memahami topik dengan lebih baik:

Max Koretskyi
sumber
33
ini harus menjadi jawaban yang diterima. sebenarnya menjelaskan MENGAPA daripada mengulangi mantra dan menyatakan the constructor should only be used to inject dependencies.
Stavm
1
@ yannick1976, terima kasih! Lihat artikel yang direferensikan
Max Koretskyi
@flobacca, bisakah Anda ulangi pertanyaannya, sulit untuk memahami apa yang Anda minta
Max Koretskyi
Harap perbaiki saya jika saya salah. Saya mengerti pohon komponen pertama kali dibangun dan kemudian mengubah proses deteksi. Anda menulis konstruktor AppComponent pertama disebut (bersama dengan dependensi yang diselesaikan) kemudian konstruktor ChildComponent disebut (bersama dengan dependensi) kemudian Input binding untuk AppComponent dan kemudian OnInit dipanggil. Tetapi yang menjadi perhatian saya adalah jika saya menambahkan kait siklus hidup ke kedua komponen, alurnya adalah AppComponentConstructor - -> AppComponentOnInit - → ChildComponentConstructor - → ChildComponentOnInit Mengapa AppComponentOnInit dipanggil sebelum ChildComponentConstructor
user2485435
1
@ MaxKoretskyiakaWizard Anda benar. Saya telah melakukan beberapa kesalahan dalam pengaturan aplikasi saya. itu bekerja seperti yang dijelaskan oleh Anda. angular-c7zjsx.stackblitz.io
user2485435
96

Saya pikir contoh terbaik adalah menggunakan layanan. Katakanlah saya ingin mengambil data dari server saya ketika komponen saya 'Diaktifkan'. Katakanlah saya juga ingin melakukan beberapa hal tambahan pada data setelah saya mendapatkannya dari server, mungkin saya mendapatkan kesalahan dan ingin mencatatnya secara berbeda.

Sangat mudah dengan ngOnInit di atas konstruktor, juga membatasi berapa banyak lapisan panggilan balik yang perlu saya tambahkan ke aplikasi saya.

Sebagai contoh:

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


}

dengan konstruktor saya, saya bisa memanggil _userService saya dan mengisi user_list saya, tapi mungkin saya ingin melakukan beberapa hal tambahan dengannya. Seperti memastikan semuanya huruf besar, saya tidak sepenuhnya yakin bagaimana data saya masuk.

Jadi membuatnya lebih mudah untuk menggunakan 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();
    };


}

Itu membuatnya lebih mudah untuk dilihat, dan jadi saya hanya memanggil fungsi saya di dalam komponen saya ketika saya menginisialisasi daripada harus menggali untuk itu di tempat lain. Sungguh itu hanyalah alat lain yang dapat Anda gunakan untuk membuatnya lebih mudah dibaca dan digunakan di masa depan. Juga saya menemukan itu benar-benar praktik buruk untuk menempatkan pemanggilan fungsi dalam sebuah konstruktor!

Morgan G
sumber
Contoh Anda dapat disederhanakan jika Anda hanya mengatur user_list ke Observable. Angular2 memiliki pipa async, jadi tidak akan ada masalah di sana.
DarkNeuron
@ Organ, hanya untuk saya mempelajari hal kecil di sini, mengapa Anda pertama kali membuat fungsi getUsersdan kemudian memasukkannya ke dalam ngOnInit? Apakah tidak kurang kode untuk hanya menuliskannya di ngOnInit? Saya hanya bertanya-tanya mengapa orang melakukannya dengan cara ini? Apakah ini agar Anda dapat menggunakan kembali kode jika Anda mau juga? Terima kasih.
Alfa Bravo
31
Seperti yang terlihat dalam jawaban di bawah ini tidak ada bedanya jika ada di konstruktor. Ini bukan jawaban nyata untuk tujuan itu.
Jimmy Kane
8
Saya tidak melihat bagaimana ini menjawab pertanyaan sama sekali. Mengapa Anda tidak bisa memasukkan kode saja ke dalam constructor?
CodyBugstein
1
@Morgan, kenapa kau tidak melakukannyaconstructor(private _userService: UserService){ this.getUsers(); };
Ashley
82

OK, pertama-tama ngOnInitadalah bagian dari siklus hidup Angular , sedangkan constructoradalah bagian dari kelas JavaScript ES6 , jadi perbedaan utama dimulai dari sini! ...

Lihatlah grafik di bawah ini yang saya buat yang menunjukkan siklus hidup Angular.

ngOnInit vs konstruktor

Di Angular2 + kita gunakan constructoruntuk melakukan itu DI(Dependency Injection)untuk kita, sementara di Angular 1 itu terjadi melalui pemanggilan ke metode String dan memeriksa ketergantungan mana yang disuntikkan.

Seperti yang Anda lihat pada diagram di atas, ngOnInitterjadi setelah konstruktor siap dan ngOnChnagesdan dipecat setelah komponen siap untuk kita. Semua inisialisasi dapat terjadi pada tahap ini, sampel sederhana menyuntikkan layanan dan inisialnya pada init.

OK, saya juga membagikan kode sampel untuk Anda lihat, lihat bagaimana kami menggunakan ngOnInitdan constructordalam kode di bawah ini:

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!');
  }
}
Alireza
sumber
1
Terima kasih. ini harus menjadi jawaban terbaik.
Don Dilanga
58

Yang pertama (konstruktor) terkait dengan instantiasi kelas dan tidak ada hubungannya dengan Angular2. Maksud saya konstruktor dapat digunakan pada kelas apa saja. Anda dapat memasukkan beberapa proses inisialisasi untuk instance yang baru dibuat.

Yang kedua sesuai dengan kait siklus hidup komponen Angular2:

Dikutip dari situs web resmi angular:

  • ngOnChanges dipanggil ketika input atau output nilai mengikat berubah
  • ngOnInit disebut setelah yang pertama ngOnChanges

Jadi, Anda harus menggunakan ngOnInitjika pemrosesan inisialisasi bergantung pada binding komponen (misalnya parameter komponen ditentukan dengan @Input), jika tidak konstruktor akan cukup ...

Thierry Templier
sumber
49

Saya hanya akan menambahkan satu hal penting yang terlewati dalam penjelasan di atas dan menjelaskan kapan Anda HARUS menggunakan ngOnInit.

Jika Anda melakukan manipulasi DOM komponen melalui mis. ViewChildren , ContentChildren atau ElementRef , elemen asli Anda tidak akan tersedia selama fase konstruktor.

Namun, sejak ngOnInitterjadi begitu komponen telah dibuat dan pemeriksaan ( ngOnChanges) telah dipanggil, Anda dapat mengakses DOM pada titik ini.

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
  }
}
Miroslav Jonas
sumber
3
Nggak. Untuk @ViewChildrenkhususnya, Anda perlu menggunakan ngAfterViewInitmetode ini. Lihat di sini: stackoverflow.com/questions/46314734/…
AsGoodAsItGets
1
Terima kasih, @ AsGoodAsItGets untuk menunjukkannya. Saya sekarang telah memperbaiki jawabannya
Miroslav Jonas
38

Jawaban singkat dan sederhana adalah,

Constructor: constructoradalah default methodjalan ( dengan tuli ) ketika komponen sedang dibangun. Ketika Anda membuat an instancekelas waktu itu juga constructor(default method)akan dipanggil. Jadi dengan kata lain, ketika komponen sedang constructed or/and an instance is created constructor(default method)dipanggil dan kode yang relevan tertulis di dalamnya disebut. Pada dasarnya dan umumnya di Angular2dalamnya digunakan untuk menyuntikkan hal-hal seperti servicesketika komponen sedang dibangun untuk penggunaan lebih lanjut.

OnInit: ngOnInit adalah kait siklus hidup komponen yang berjalan pertama setelah constructor(default method)saat komponen diinisialisasi.

Jadi, konstruktor Anda akan dipanggil terlebih dahulu dan Oninit akan dipanggil nanti setelah metode konstruktor.

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

Sumber: Kait siklus hidup

Anda dapat memeriksa demo kecil ini yang menunjukkan implementasi kedua hal tersebut.

mikronik
sumber
5
Saya pikir "konstruktor adalah sesuatu yang berjalan atau dipanggil ketika komponen diinisialisasi." menyesatkan. Konstruktor adalah fitur kelas bukan komponen. Saya akan mengatakan instance kelas hanya menjadi komponen setelah konstruktor dipanggil dan Angular melakukan inisialisasi.
Günter Zöchbauer
Ya, ubah pernyataan yang dapat Anda periksa sekarang.
micronyks
1
Hmm, IMHO itu masih sama "konstruktor (metode default) adalah sesuatu yang berjalan atau dipanggil ketika komponen dibangun.". Itu tidak hanya dipanggil ketika komponen dibangun tetapi juga untuk layanan atau ketika kode suka new MyClass()dijalankan. Saya pikir itu menyesatkan untuk mengatakan konstruktor adalah tentang komponen, mereka tentang kelas dan menginisialisasi contoh dari kelas-kelas ini. Komponen kebetulan adalah kelas semacam itu. Kalau tidak, saya pikir itu jawaban yang bagus.
Günter Zöchbauer
2
Ya, tentu saja. Lupa menyebutkan bahwa ketika Anda membuat objek kelas juga waktu constructoritu akan dipanggil. Tetapi jawaban ini telah ditulis dalam konteks angular2. Untuk mengetahui jawaban terbaik Anda harus mengetahui dasar-dasar OOP. Tetap saya akan memperbarui jawaban.
micronyks
@ GünterZöchbauer, saya tidak berpikir bahwa ini adalah pernyataan yang benar bahwa ini adalah fitur dari kelas bukan dari komponen . Dari perspektif bahasa pemrograman ya, ini benar. Tapi saya bisa berhasil bekerja dengan komponen tanpa kait siklus hidup sama sekali. Tetapi saya tidak dapat bekerja dengan komponen tanpa konstruktor jika saya perlu DI karena itu satu-satunya tempat injeksi. Lihat jawaban saya
Max Koretskyi
20

Seperti banyak bahasa lain, Anda dapat menginisialisasi variabel di tingkat kelas, konstruktor, atau metode. Terserah pengembang untuk memutuskan apa yang terbaik dalam kasus khusus mereka. Tetapi di bawah ini adalah daftar praktik terbaik ketika harus memutuskan.

Variabel tingkat kelas

Biasanya, Anda akan mendeklarasikan semua variabel Anda di sini yang akan digunakan di komponen Anda yang lain. Anda dapat menginisialisasi mereka jika nilainya tidak bergantung pada hal lain, atau menggunakan kata kunci const untuk membuat konstanta jika mereka tidak akan berubah.

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

Konstruktor

Biasanya itu praktik terbaik untuk tidak melakukan apa pun di konstruktor dan hanya menggunakannya untuk kelas yang akan disuntikkan. Sebagian besar konstruktor Anda akan terlihat seperti ini:

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

ini secara otomatis akan membuat variabel tingkat kelas, sehingga Anda akan memiliki akses customService.myMethod()tanpa harus melakukannya secara manual.

NgOnInit

NgOnit adalah pengait siklus hidup yang disediakan oleh kerangka Angular 2. Komponen Anda harus menerapkan OnInituntuk menggunakannya. Kait siklus hidup ini dipanggil setelah konstruktor dipanggil dan semua variabel diinisialisasi. Sebagian besar inisialisasi Anda harus di sini. Anda akan memiliki kepastian bahwa Angular telah menginisialisasi komponen Anda dengan benar dan Anda dapat mulai melakukan logika apa pun yang Anda perlukan OnInitdibandingkan melakukan hal-hal ketika komponen Anda belum selesai memuat dengan benar.

Berikut ini adalah gambar yang merinci urutan panggilan:

masukkan deskripsi gambar di sini

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

TLDR

Jika Anda menggunakan kerangka kerja Angular 2 dan perlu berinteraksi dengan peristiwa siklus hidup tertentu, gunakan metode yang disediakan oleh kerangka kerja ini untuk menghindari masalah.

Eduardo Dennis
sumber
19

Untuk menguji ini, saya menulis kode ini, meminjam dari Tutorial 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;
  }

}

Output konsol

JS: *** User class constructor property ***  
JS: *** User class constructor constructor ***  
JS: *** Login Component Constructor ***  
JS: *** User class constructor ngOnInit ***  
JS: *** Login Component ngOnInit ***  
abbaf33f
sumber
18

Perbedaan utama antara konstruktor dan ngOnInitbahwa itu ngOnInitadalah siklus hidup kait dan berjalan setelah konstruktor. Templat interpolasi komponen dan input nilai awal tidak tersedia di konstruktor, tetapi tersedia di ngOnInit.

Perbedaan praktisnya adalah bagaimana ngOnInitmemengaruhi bagaimana kode disusun. Sebagian besar kode inisialisasi dapat dipindahkan ke ngOnInit- selama ini tidak menciptakan kondisi balapan .

Antipattern konstruktor

Sejumlah besar kode inisialisasi membuat metode konstruktor sulit untuk diperluas, dibaca dan diuji.

Resep biasa untuk memisahkan logika inisialisasi dari konstruktor kelas adalah memindahkannya ke metode lain seperti init:

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

  init() {...}
}

ngOnInit dapat melayani tujuan ini dalam komponen dan arahan:

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

ngOnInit() {
  // rest of initialization code
}

Ketergantungan injeksi

Peran utama konstruktor kelas di Angular adalah injeksi ketergantungan. Konstruktor juga digunakan untuk anotasi DI dalam TypeScript. Hampir semua dependensi ditugaskan sebagai properti ke instance kelas.

Konstruktor komponen / direktif rata-rata sudah cukup besar karena dapat memiliki tanda tangan multiline karena dependensi, menempatkan logika intialisasi yang tidak perlu untuk berkontribusi bagi badan konstruktor ke antipattern.

Inisialisasi tidak sinkron

Inisialisasi konstruktor asinkron sering dapat dianggap antipattern dan memiliki bau karena kelas selesai sebelum rutin asinkron tidak, dan ini dapat menciptakan kondisi balapan. Jika bukan itu masalahnya, ngOnInitdan kait siklus hidup lainnya adalah tempat yang lebih baik untuk ini, terutama karena mereka dapat mengambil manfaat dari asyncsintaks:

constructor(
  public foo: Foo,
  public errorHandler: ErrorHandler
) {}

async ngOnInit() {
  try {
    await this.foo.getBar();
    await this.foo.getBazThatDependsOnBar();
  } catch (err) {
    this.errorHandler.handleError(err);
  }
}

Jika ada kondisi balapan (termasuk salah satu yang komponen tidak boleh muncul pada kesalahan inisialisasi), rutin inisialisasi asinkron harus dilakukan sebelum instantiasi komponen dan dipindahkan ke komponen induk, pelindung router, dll.

Pengujian unit

ngOnInitlebih fleksibel daripada konstruktor dan memberikan beberapa manfaat untuk pengujian unit yang dijelaskan secara rinci dalam jawaban ini .

Menimbang bahwa ngOnInittidak dipanggil secara otomatis pada kompilasi komponen dalam unit test, metode yang dipanggil ngOnInitdapat dimata-matai atau diejek setelah instantiasi komponen.

Dalam kasus luar biasa ngOnInitdapat sepenuhnya dihapus untuk memberikan isolasi untuk unit komponen lain (misalnya, beberapa logika templat).

Warisan

Kelas anak hanya dapat menambah konstruktor, bukan menggantikannya.

Karena thistidak dapat dirujuk sebelumnya super(), ini menempatkan pembatasan pada prioritas inisialisasi.

Menimbang bahwa komponen Angular atau penggunaan direktif ngOnInituntuk logika inisialisasi yang tidak sensitif terhadap waktu, kelas anak dapat memilih apakah super.ngOnInit()dipanggil dan kapan:

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

Ini tidak mungkin diterapkan dengan konstruktor saja.

Estus Flask
sumber
12

Jawaban di atas tidak benar-benar menjawab aspek pertanyaan awal ini: Apa itu siklus hidup? Butuh beberapa saat untuk memahami apa artinya sampai saya memikirkannya seperti ini.

1) Katakan komponen Anda adalah manusia. Manusia memiliki kehidupan yang mencakup banyak tahap kehidupan, dan kemudian kita berakhir.

2) Komponen manusia kita dapat memiliki skrip siklus hidup berikut: Lahir, Bayi, Sekolah Dasar, Dewasa Muda, Dewasa Paruh Baya, Dewasa Senior, Mati, Dibuang.

3) Katakan Anda ingin memiliki fungsi untuk membuat anak-anak. Agar ini tidak rumit, dan agak lucu, Anda ingin fungsi Anda hanya dipanggil selama tahap Dewasa Muda dari kehidupan komponen manusia. Jadi, Anda mengembangkan komponen yang hanya aktif ketika komponen induk dalam tahap Dewasa Muda. Hooks membantu Anda melakukan itu dengan memberi sinyal pada tahap kehidupan itu dan membiarkan komponen Anda bertindak.

Hal menyenangkan. Jika Anda membiarkan imajinasi Anda benar-benar mengkodekan sesuatu seperti ini, itu menjadi rumit, dan lucu.

Preston
sumber
7

The konstruktor adalah metode dalam JavaScript dan dianggap sebagai fitur dari kelas di ES6 .Ketika kelas yang dipakai segera berjalan konstruktor apakah itu digunakan dalam rangka sudut atau not.So yang disebut oleh mesin JavaScript dan sudut tidak memiliki kontrol itu.

import {Component} from '@angular/core';
@Component({})
class CONSTRUCTORTEST {

//This is called by Javascript not the Angular.
     constructor(){
        console.log("view constructor initialised");
     }
}

Kelas "ConstructorTest" dibuat di bawah ini; Jadi secara internal memanggil konstruktor (Semua ini terjadi oleh JavaScript (es6) no Angular).

new CONSTRUCTORTEST();

Itulah sebabnya ada ngOnInit siklus hidup kait di Angular.ngOnInit merender ketika sudut selesai inisialisasi komponen.

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

Pertama kita instantiate kelas seperti di bawah ini yang terjadi pada langsung menjalankan metode konstruktor.

let instance = new NGONINITTEST();

ngOnInit dipanggil oleh Angular bila perlu seperti di bawah ini:

instance.ngOnInit();

Tetapi Anda mungkin bertanya mengapa kami menggunakan konstruktor di Angular?

Jawabannya adalah injeksi dependensi . Seperti yang disebutkan sebelumnya, panggilan konstruktor oleh mesin JavaScript segera ketika kelas instantiated (sebelum memanggil ngOnInit oleh Angular), jadi naskah membantu kita untuk mendapatkan jenis dependensi yang ditentukan dalam konstruktor dan akhirnya memberitahu Sudut jenis dependensi apa yang ingin kita gunakan dalam komponen spesifik itu.

Negin
sumber
7

Dua hal yang perlu diperhatikan di sini:

  1. Konstruktor dipanggil setiap kali sebuah objek dibuat dari kelas itu.
  2. ngOnInit dipanggil setelah komponen dibuat.

Keduanya memiliki kegunaan yang berbeda.

UniCoder
sumber
5

constructor () adalah metode default dalam siklus hidup Komponen dan digunakan untuk injeksi dependensi. Konstruktor adalah Fitur Ketik.

ngOnInit () dipanggil setelah konstruktor dan ngOnInit dipanggil setelah ngOnChanges pertama.

yaitu:

Konstruktor () -->ngOnChanges () -->ngOnInit ()

seperti yang disebutkan di atas ngOnChanges()disebut ketika input atau output mengikat nilai berubah.

Shajin Chandran
sumber
4

Kedua metode memiliki tujuan / tanggung jawab yang berbeda. Tugas konstruktor (yang merupakan fitur yang didukung bahasa) adalah untuk memastikan bahwa representasi invarian berlaku. Sebaliknya dinyatakan untuk memastikan bahwa instance tersebut valid dengan memberikan nilai yang benar kepada anggota. Terserah pengembang untuk memutuskan apa artinya 'benar'.

Tugas metode onInit () (yang merupakan konsep sudut) adalah untuk memungkinkan pemanggilan metode pada objek yang benar (representasi invarian). Setiap metode pada gilirannya harus memastikan bahwa invarian representasi berlaku ketika metode berakhir.

Konstruktor harus digunakan untuk membuat objek 'benar', metode onInit memberi Anda kesempatan untuk memanggil pemanggilan metode pada instance yang didefinisikan dengan baik.

Bruno Ranschaert
sumber
4

Konstruktor: Metode konstruktor pada kelas ES6 (atau TypeScript dalam kasus ini) adalah fitur dari kelas itu sendiri, bukan fitur Angular. Itu di luar kendali Angular ketika konstruktor dijalankan, yang berarti itu bukan pengait yang cocok untuk memberi tahu Anda ketika Angular telah selesai menginisialisasi komponen. Mesin JavaScript memanggil konstruktor, bukan Angular secara langsung. Itulah sebabnya kait siklus hidup ngOnInit (dan $ onInit di AngularJS) dibuat. Mengingat hal ini, ada skenario yang cocok untuk menggunakan konstruktor. Inilah saatnya kita ingin menggunakan injeksi ketergantungan - pada dasarnya untuk dependensi "kabel" ke dalam komponen.

Karena konstruktor diinisialisasi oleh mesin JavaScript, dan TypeScript memungkinkan kita untuk memberi tahu Angular dependensi apa yang perlu dipetakan terhadap properti tertentu.

ngOnInit ada di sana untuk memberi kami sinyal bahwa Angular telah selesai menginisialisasi komponen.

Fase ini mencakup lintasan pertama di Change Detection terhadap properti yang dapat kita ikat ke komponen itu sendiri - seperti menggunakan dekorator @Input ().

Karena ini, properti @Input () tersedia di dalam ngOnInit, namun tidak ditentukan di dalam konstruktor, berdasarkan desain

Vishal Gulati
sumber
2

Konstruktor adalah yang pertama, dan kadang-kadang terjadi ketika data input nol! jadi kami menggunakan Konstruktor untuk menyatakan layanan dan ngOnInit terjadi setelahnya. Contoh untuk pengawas:

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

Contoh untuk onInit:

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

Saya pikir onInit seperti InitialComponents () di winForm.

pengguna1012506
sumber
1

Dalam siklus hidup Angular

1) Injektor sudut mendeteksi parameter konstruktor dan kelas instantiate.

2) Siklus hidup panggilan sudut berikutnya

Kait Siklus Hidup Sudut

ngOnChanges -> Panggilan dalam parameter direktif mengikat.

ngOnInit -> Mulai rendering sudut ...

Sebut metode lain dengan siklus hidup sudut.

Muslim Shahsavan
sumber
1

The constructordipanggil saat Sudut "instanciates / konstruksi" komponen. The ngOnInitmetode adalah hook yang merupakan bagian inisialisasi dari siklus hidup komponen. Praktik yang baik adalah menggunakannya hanya untuk injeksi layanan :

constructor(private 
    service1: Service1,
    service2: Service2
){};

Bahkan jika itu mungkin, Anda tidak harus melakukan "pekerjaan" di dalam. Jika Anda ingin meluncurkan beberapa tindakan yang harus terjadi pada komponen "inisialisasi", gunakan ngOnInit:

ngOnInit(){
    service1.someWork();
};

Selain itu, tindakan yang melibatkan properti input , yang berasal dari komponen induk, tidak dapat dilakukan di konstruktor. Mereka harus ditempatkan dalam ngOnInitmetode atau pengait lain. Itu sama untuk elemen yang terkait dengan tampilan (DOM), misalnya, elemen viewchild :

@Input itemFromParent: string;
@ViewChild('childView') childView;

constructor(){
    console.log(itemFromParent); // KO
    // childView is undefined here
};

ngOnInit(){
    console.log(itemFromParent); // OK
    // childView is undefined here, you can manipulate here
};
veben
sumber
0

constructor() digunakan untuk melakukan injeksi ketergantungan.

ngOnInit(), ngOnChanges()dan ngOnDestroy()lain-lain adalah metode siklus hidup. ngOnChanges()akan menjadi yang pertama dipanggil, sebelum ngOnInit(), ketika nilai properti terikat berubah, itu TIDAK akan dipanggil jika tidak ada perubahan. ngOnDestroy()dipanggil saat komponen dihapus. Untuk menggunakannya, OnDestroyperlu implementdiedit oleh kelas.

xameeramir
sumber
1
setuju, ini singkat dan jelas. Misalnya, constructor () adalah untuk menambahkan objek layanan, ngOnInit () adalah untuk memanipulasi komponen dengan panggilan fungsi layanan yang diperlukan.
Steve
0

Saya menemukan jawabannya dan saya mencoba menerjemahkannya ke bahasa Inggris: Pertanyaan ini masih muncul, bahkan dalam wawancara teknis. Bahkan, ada kemiripan yang besar di antara keduanya, tetapi juga ada beberapa perbedaan.

  • Konstruktor adalah bagian dari ECMAScript. Di sisi lain ngOnInit () adalah gagasan sudut.

  • Kita dapat memanggil konstruktor di semua kelas bahkan jika kita tidak menggunakan Angular

  • LifeCycle: Konstruktor dipanggil sebelum ngOnInt ()

  • Dalam konstruktor kita tidak dapat memanggil elemen HTML. Namun, di ngOnInit () kita bisa.

  • Secara umum, panggilan layanan di ngOnInit () dan tidak di dalam konstruktor

    Sumber: http://www.angular-tuto.com/Angular/Component#Diff

Doudou
sumber
0

Konstruktor

Fungsi konstruktor dilengkapi dengan setiap kelas, konstruktor tidak spesifik untuk Angular tetapi konsep yang berasal dari desain berorientasi objek. Konstruktor membuat turunan dari kelas komponen.

Aktifkan

The ngOnInitFungsi adalah salah satu metode siklus hidup komponen sudut ini. Metode siklus hidup (atau pengait) dalam komponen Angular memungkinkan Anda menjalankan sepotong kode pada berbagai tahapan umur komponen. Tidak seperti metode konstruktor, ngOnInitmetode berasal dari antarmuka Angular ( OnInit) yang perlu diimplementasikan oleh komponen untuk menggunakan metode ini. The ngOnInitmetode ini disebut tak lama setelah komponen dibuat.

DeC
sumber
0

Konstruktor dieksekusi ketika kelas dipakai. Tidak ada hubungannya dengan sudut. Ini adalah fitur Javascript dan Angular tidak memiliki kontrol atasnya

NgOnInit adalah spesifik Angular dan disebut ketika Angular telah menginisialisasi komponen dengan semua properti inputnya

Properti @Input tersedia di bawah kait siklus hidup ngOnInit. Ini akan membantu Anda untuk melakukan beberapa hal inisialisasi seperti mendapatkan data dari server back-end dll untuk ditampilkan dalam tampilan

@Input properti ditampilkan sebagai tidak terdefinisi di dalam konstruktor

dasunse
sumber
-1

Konstruktor adalah fungsi yang dieksekusi ketika komponen (atau kelas lain) dibangun.

ngOnInit adalah fungsi yang termasuk dalam grup metode siklus hidup komponen dan dieksekusi dalam momen yang berbeda dengan komponen kami (itulah sebabnya beri nama siklus hidup). Berikut adalah daftar semuanya:

masukkan deskripsi gambar di sini Konstruktor akan dieksekusi sebelum fungsi siklus-hidup.

Przemek Struciński
sumber