web-dev-qa-db-ja.com

コンストラクタとngOnInitの違い

Angularは、デフォルトでライフサイクルフックngOnInitを提供します。

すでにngOnInitがあるのに、なぜconstructorを使うべきなのでしょうか。

693
Haseena P A

Constructorは、クラスがインスタンス化されるときに実行され、クラスとそのサブクラス内のフィールドの適切な初期化を保証するクラスのデフォルトメソッドです。 Angular以上のDependency Injector(DI)はコンストラクタパラメータを分析し、new MyClass()を呼び出して新しいインスタンスを作成するときに、コンストラクタパラメータの型に一致するプロバイダを探し、それらを解決してコンストラクタに渡します好き

new MyClass(someArg);

ngOnInitは、Angular2によって呼び出されるライフサイクルフックで、Angularがコンポーネントの作成を完了したことを示します。

このように使うためにはOnInitをインポートする必要があります(実際にOnInitを実装することは必須ではありませんが、良い方法と考えられています):

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

OnInitのメソッドを使うためには、このようにクラスに実装しなければなりません。

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

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

このインターフェースを実装して、ディレクティブのデータバインドプロパティが初期化された直後にカスタム初期化ロジックを実行します。 ngOnInitは、ディレクティブのデータバインドプロパティが最初にチェックされた直後の直前その子供たちのいずれかがチェックされています。 ディレクティブがインスタンス化されるときに一度だけ呼び出されます。

ほとんどの場合、初期化/宣言のすべてにngOnInitを使用し、コンストラクタ内で機能するものを避けます。コンストラクタはクラスメンバを初期化するためだけに使われるべきですが、実際の "仕事"をするべきではありません。

そのため、Dependency Injectionを設定するにはconstructor()を使用する必要があります。 ngOnInit()は「開始」するのに適した場所です。コンポーネントのバインディングが解決される場所/場所です。

詳しくはこちらを参照してください。

785
Pardeep Jain

記事 Angular のConstructorとngOnInitの本質的な違いは、複数の観点からの違いを探るものです。この回答では、コンポーネントの初期化プロセスに関する最も重要な違いについて説明します。

角度付きブートストラッププロセスは、2つの主要な段階で構成されています。

  • コンポーネントツリーの構築
  • ランニングチェンジ検出

Angularがコンポーネントツリーを構築するときに、コンポーネントのコンストラクタが呼び出されます。すべてのライフサイクルフックは、実行中の変更検出の一部として呼び出されます。 

Angularがコンポーネントツリーを構築するとき、ルートモジュールインジェクタは既に設定されているので、グローバルな依存関係を注入することができます。また、Angularが子コンポーネントクラスをインスタンス化するとき、親コンポーネントのインジェクタもすでに設定されているので、親コンポーネント自体を含む親コンポーネントで定義されたプロバイダをインジェクトでき​​ます。コンポーネントコンストラクタは、インジェクタのコンテキストで呼び出される唯一のメソッドなので、依存関係が必要な場合は、それらの依存関係を取得するための唯一の場所です。

Angularが変更検出を開始すると、コンポーネントツリーが構築され、ツリー内のすべてのコンポーネントのコンストラクタが呼び出されます。また、すべてのコンポーネントのテンプレートノードがDOMに追加されます。 @Input通信メカニズムは変更検出時に処理されるため、コンストラクタで利用可能なプロパティを持つことは期待できません。それはngOnInitの後に利用可能になるでしょう。

簡単な例を見てみましょう。次のようなテンプレートがあるとします。

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

そのため、Angularはアプリケーションのブートストラップを開始します。私が言ったように、最初に各コンポーネントのクラスを作成します。それでMyAppComponentコンストラクタを呼び出します。 my-appコンポーネントのHost要素であるDOMノードも作成します。それからchild-compのHost要素の作成とChildComponentコンストラクタの呼び出しに進みます。この段階では、それはi入力バインディングやライフサイクルフックにはあまり関係ありません。したがって、このプロセスが終了すると、Angularは次のようなコンポーネントビューのツリーになります。

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

変更検出を実行してmy-appのバインディングを更新し、MyAppComponentクラスのngOnInitを呼び出します。それからchild-compのバインディングの更新に進み、ChildComponentクラスのngOnInitを呼び出します。

必要なものに応じて、初期化ロジックをコンストラクターまたはngOnInitのいずれかで実行できます。たとえば、_ @ViewChildクエリが評価される前にViewContainerRefを取得する方法は、次のようになります。 コンストラクタ内で実行するために必要な初期化ロジックの種類を示します。

トピックを理解するのに役立つ記事がいくつかあります。

最良の例はサービスを利用することでしょう。コンポーネントが「アクティブ」になったときにサーバーからデータを取得したいとしましょう。サーバーからデータを取得した後で、そのデータに対して追加の処理を実行したいとします。エラーが発生したため、ログ記録を変更したい場合があります。

それは、コンストラクタを介して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();
    };


}

見やすくなりますので、初期化時に自分のコンポーネント内で自分の関数を呼び出すだけで、他の場所でDigを実行する必要はありません。本当にそれはあなたがそれを将来読みやすくそして使いやすくするためにあなたが使うことができるもう一つのツールです。また、コンストラクタ内に関数呼び出しを入れるのは本当に悪い習慣です。

81
Morgan G

OK、 まず第一にngOnInit Angular lifecycle の一部ですが、constructor ES6 JavaScriptクラスの一部なので、大きな違いが始まりますここから!.

私が作成した下のグラフを見てください。これはAngularのライフサイクルを示しています。

ngOnInit vs constructor

Angular 2 +では、DI(Dependency Injection)を実行するためにconstructorを使用していますが、Angular 1では、Stringメソッドを呼び出してどの依存関係が注入されたかを確認することで発生していました。 

上の図に見られるように、ngOnInitはコンストラクタの準備が整った後に発生し、ngOnChnagesはコンポーネントの準備が整った後に発生します。すべての初期化はこの段階で発生する可能性があります。簡単なサンプルでサービスを投入し、initで初期化します。

わかりました、私はあなたが見るためのサンプルコードも共有しています。以下のコードでどのようにngOnInitconstructorが使われるかを見てください:

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

最初のもの(コンストラクタ)はクラスのインスタンス化に関連しており、Angular 2とは関係ありません。コンストラクタはどのクラスでも使用できるということです。新しく作成したインスタンスの初期化処理をその中に入れることができます。

2番目のものはAngular 2コンポーネントのライフサイクルフックに対応します。

公式の角度のウェブサイトからの引用:

  • 入力または出力バインディング値が変更されるとngOnChangesが呼び出されます
  • ngOnInitは最初のngOnChangesの後に呼び出されます

そのため、初期化処理がコンポーネントのバインディングに依存している場合はngOnInitを使用する必要があります(たとえば、@Inputで定義されたコンポーネントパラメータなど)。それ以外の場合はコンストラクタで十分です。

44

短くて簡単な答えは、だろう

Constructorconstructorは、コンポーネントの構築時にdefault methodが実行される(by deafult)です。そのときクラスのan instanceを作成すると、constructor(default method)も呼び出されます。つまり言い換えれば、componentがconstructed or/and an instance is created constructor(default method)と呼ばれていて、その中に書かれている関連コードが呼ばれているということです。基本的にそして一般的にAngular2では、コンポーネントがさらなる使用のために構築されているときにservicesのようなものを注入するために使用されていました。

OnInit:ngOnInitは、コンポーネントの初期化時にconstructor(default method)の後に最初に実行されるコンポーネントのライフサイクルフックです。 

ですから、あなたのコンストラクタが最初に呼ばれ、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() 
   }
}

リソース:LifeCycleフック

あなたはこれをチェックすることができます小さなデモこれは両方の実装を示しています。

27
micronyks

上記の説明でスキップした重要なことを1つ追加して、 _が_ / ngOnInitを使用する必要がある場合について説明します。

あなたがコンポーネントを介してコンポーネントのDOMの任意の操作をしているならば。 ViewChildren ContentChildren または ElementRef 、ネイティブエレメントはコンストラクターフェーズでは使用できません。

ただし、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
  }
}
24
Miroslav Jonas

これをテストするために、 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 ***  
16
jmb-mage

コンストラクタとngOnInitの主な違いは、ngOnInitライフサイクルフック であり、コンストラクタの後に実行されることです。コンポーネント補間テンプレートと入力初期値はコンストラクタでは利用できませんが、ngOnInitでは利用できます。

実際の違いは、ngOnInitがコードの構造にどのように影響するかです。ほとんどの初期化コードはngOnInit - これが競合状態にならない限りに移動できます。

コンストラクタアンチパターン

かなりの量の初期化コードがあるため、コンストラクタメソッドを拡張、読み取り、テストすることは困難です。

初期化ロジックをクラスコンストラクタから分離するための通常のレシピは、それをinitのような別のメソッドに移動することです。

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

  init() {...}
}

ngOnInitは、コンポーネントとディレクティブでこの目的を果たすことができます。

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

ngOnInit() {
  // rest of initialization code
}

依存性注入

Angularにおけるクラスコンストラクターの主な役割は、依存性注入です。コンストラクタは、TypeScriptのDI注釈にも使用されます。ほとんどすべての依存関係は、プロパティとしてクラスインスタンスに割り当てられます。

平均的なコンポーネント/ディレクティブコンストラクタは、依存関係のために複数行のシグネチャを持つことができるため、コンストラクタ本体に不要な初期化ロジックを配置することで、アンチパターンに寄与するため、すでに十分な大きさです。

非同期初期化

非同期初期化コンストラクタは、非同期ルーチンが終了する前にクラスのインスタンス化が終了し、競合状態が発生する可能性があるため、多くの場合、アンチパターン化および匂いがあると考えられます。そうでない場合は、特にngOnInit構文の恩恵を受ける可能性があるため、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);
  }
}

競合状態が発生した場合(コンポーネントが初期化エラーに現れてはならないという条件を含む)、非同期初期化ルーチンはコンポーネントのインスタンス化の前に行われ、親コンポーネント、ルーターガードなどに移動されるべきです。

単体テスト

ngOnInitはコンストラクタよりも柔軟性があり、単体テストにいくつかの利点を提供します。詳細は この回答 で説明されています。

単体テストでは、コンポーネントのコンパイル時にngOnInitが自動的に呼び出されないことを考慮すると、ngOnInitで呼び出されるメソッドは、コンポーネントのインスタンス化後にスパイまたはモックされる可能性があります。

例外的なケースでは、ngOnInitを完全にスタブ化して他のコンポーネントユニット(たとえば、テンプレートロジック)を分離することができます。

継承

子クラスはコンストラクタを増やすことができるだけで、それらを置き換えることはできません。

thissuper()の前に参照することができないので、これは初期化の優先順位に制限を置きます。

Angularコンポーネントまたはディレクティブが時間に依存しない初期化ロジックにngOnInitを使用することを考慮すると、子クラスはsuper.ngOnInit()が呼び出されるかどうか、および次の場合に選択できます。

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

これはコンストラクタだけでは実装できません。

14
estus

他の多くの言語と同様に、クラスレベル、コンストラクター、またはメソッドで変数を初期化できます。特定のケースに最適なものを決定するのは開発者次第です。しかし、以下は決定する際のベストプラクティスのリストです。

クラスレベル変数 

通常、あなたはここであなたのすべての変数を宣言します。それはあなたのコンポーネントの残りの部分で使われます。値が他に依存していない場合は初期化できます。変更しない場合はconstキーワードを使用して定数を作成できます。

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

コンストラクタ

通常、コンストラクタ内では何もせずに、注入されるクラスに使用することをお勧めします。ほとんどの場合、コンストラクタは次のようになります。

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

これは自動的にクラスレベル変数を作成するので、あなたはそれを手動でする必要なしにcustomService.myMethod()へアクセスすることができます。

NgOnInit

NgOnitはAngular 2フレームワークによって提供されるライフサイクルフックです。あなたのコンポーネントはそれを使うためにOnInitを実装しなければなりません。このライフサイクルフックは、コンストラクタが呼び出され、すべての変数が初期化された後に呼び出されます。あなたの初期化の大部分はここに行くべきです。あなたはAngularがあなたのコンポーネントを正しく初期化したという確信を持つでしょう、そしてあなたがあなたのコンポーネントが正しくロードを終えなかった時に物事を行うことに対してあなたはOnInitであなたが必要とするロジック 

これが呼ばれる順番の詳細を示す画像です。

enter image description here

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

TLDR 

Angular 2フレームワークを使用していて、特定のライフサイクルイベントと対話する必要がある場合は、問題を回避するためにフレームワークによって提供されているメソッドを使用してください。

13
Eduardo Dennis

上記の回答は、元の質問のこの側面には実際には答えていません。ライフサイクルフックとは何ですか?このように考えるまで、それが何を意味するのか理解するのにしばらく時間がかかりました。

1)あなたのコンポーネントが人間だとしましょう。人間は生活の多くの段階を含む生活をしており、それから私たちは期限切れになります。 

2)私たちの人的要素は、次のライフサイクル・スクリプトを持つことができます:生まれ、赤ちゃん、小学校、若年成人、中年成人、高齢者、死者、処分。

3)子供をつくる機能が欲しいとしましょう。これが複雑になりユーモラスになるのを防ぐために、あなたは自分の関数が人間の構成要素の人生のヤングアダルト段階の間だけ呼ばれることを望みます。したがって、親コンポーネントがヤングアダルト段階にあるときにのみアクティブになるコンポーネントを開発します。フックはあなたがその人生のその段階を知らせ、あなたの構成要素にそれに作用させることによってあなたがそれをするのを助けます。

楽しいものあなたが想像力をこのようなものに実際にコーディングすることを可能にするならば、それは複雑で面白いものになります。

11
Preston

コンストラクタ はJavaScriptのメソッドであり、es6ではクラスの機能と見なされます。クラスがインスタンス化されると、Angularで使用されているかどうかにかかわらずすぐにコンストラクタが実行されます_ frameworkかどうか。JavaScriptエンジンによって呼び出され、Angularはそれを制御できません。 

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

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

"ConstructorTest"クラスは以下のようにインスタンス化されているので、内部的にコンストラクタを呼び出します(これらはすべてJavaScript(es6)Angularではありません)。

new CONSTRUCTORTEST();

Angular.ngOnInitに ngOnInit lifecycleフックがあるのは、Angularがコンポーネントの初期化を終了したときにレンダリングされるからです。

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

まず、コンストラクタメソッドを直接実行したときに起こるクラスを以下のようにインスタンス化します。

let instance = new NGONINITTEST();

以下のように、必要に応じてngOnInitがAngularによって呼び出されます。

instance.ngOnInit();

しかし、なぜAngularでコンストラクタを使用しているのでしょうか。

答えは 依存関係の注入 です。前述したように、コンストラクタはクラスがインスタンス化されるとすぐに(AngularによってngOnInitが呼び出される前に)JavaScriptエンジンによって呼び出されるので、TypeScriptは依存関係はコンストラクタで定義され、最後にAngularに、その特定のコンポーネントで使用したい依存関係の種類を指示します。

7
Negin

ここで注意することが2つあります。

  1. そのクラスのオブジェクトが作成されるたびにコンストラクタが呼び出されます。 
  2. コンポーネントが作成されると、ngOnInitが呼び出されます。 

どちらも使いやすさが異なります。

7
UniCoder

コンストラクタ: ES6クラス(またはこの場合はTypeScript)のコンストラクタメソッドは、Angular機能ではなく、クラス自体の機能です。コンストラクタが呼び出されたときはAngularの制御外です。つまり、Angularがコンポーネントの初期化を終了したことを知らせるのは適切なフックではありません。 JavaScriptエンジンは直接Angularではなくコンストラクターを呼び出します。 ngOnInit(そしてAngularJSでは$ onInit)ライフサイクルフックが作成されたのはそのためです。これを念頭に置いて、コンストラクタを使用するのに適したシナリオがあります。これは、依存性注入を利用したいときです - 本質的に依存関係をコンポーネントに「配線する」ためです。

コンストラクタはJavaScriptエンジンによって初期化されるので、TypeScriptによってAngularに特定のプロパティに対してどの依存関係をマッピングする必要があるかを伝えることができます。

ngOnInit はAngularがコンポーネントの初期化を完了したことを示すシグナルを提供するためのものです。

このフェーズには、@Input()デコレータの使用など、コンポーネント自体にバインドする可能性があるプロパティに対する変更検出の最初のパスが含まれます。

このため、@Input()プロパティはngOnInit内で使用できますが、設計上、コンストラクタ内では未定義です。

4
Vishal Gulati

どちらの方法にも、異なる目標/責任があります。コンストラクタ(これは言語サポート機能です)の仕事は表現不変式が成り立つことを確認することです。そうでなければ、インスタンスに正しい値をメンバに与えることでインスタンスが有効であることを確認するように述べました。 「正しい」とはどういう意味かを決めるのは開発者次第です。

OnInit()メソッド(これは角度の概念です)のタスクは、正しいオブジェクトに対するメソッド呼び出しを可能にすることです(表現不変)。各メソッドは、メソッドが終了したときに表現不変式が成り立つようにする必要があります。

コンストラクタを使用して「正しい」オブジェクトを作成する必要があります。onInitメソッドを使用すると、明確に定義されたインスタンスでメソッド呼び出しを呼び出すことができます。

4

constructor() は、コンポーネントのライフサイクルにおけるデフォルトのメソッドで、依存関係の注入に使用されます。コンストラクタはTypeScriptの機能です。

ngOnInit() はコンストラクターの後に呼び出され、ngOnInitは最初のngOnChangesの後に呼び出されます。

すなわち、コンストラクタ() - > ngOnChanges() - > ngOnInit()

前述のように、ngOnChanges()は、入力または出力バインディング値が変わると呼び出されます。

4
shajin cse

コンストラクタは最初のもので、@ input dataがnullのときに時々起こります!宣言サービスにConstructorを使い、その後にngOnInitが起こります。

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

OnInitの例:

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

OnInitはwinFormのInitialComponents()に似ていると思います。

1
user1012506

私はその答えを見つけ、それを英語に翻訳しようとしました。この質問は技術面接でも起こりました。実際、両者には大きな類似点がありますが、いくつかの違いもあります。

  • コンストラクターはECMAScriptの一部です。一方、ngOnInit()は角度の概念です。

  • Angularを使用しなくても、すべてのクラスでコンストラクタを呼び出すことができます。

  • LifeCycle:コンストラクタはngOnInt()の前に呼び出されます

  • コンストラクタではHTML要素を呼び出すことはできません。しかし、ngOnInit()では可能です。

  • 通常、コンストラクタではなくngOnInit()でサービスを呼び出します。

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

1
doudou

実際、ngOnInit()には2つの主な理由があります。

1)構築直後に複雑な初期化を実行する。

2)Angularが入力プロパティを設定した後にコンポーネントを設定する。

経験豊富な開発者は、コンポーネントは安価で安全に構築できるべきであることに同意します。

AngularチームリーダーのMisko Heveryは、なぜ複雑なコンストラクタロジックを避けるべきかを説明します。

コンポーネントのコンストラクタでデータを取得しないでください。テスト用に作成されたとき、または表示することを決定する前に、新しいコンポーネントがリモートサーバーと通信しようとしていることを心配する必要はありません。コンストラクタは初期ローカル変数を単純な値に設定するだけです。

NgOnInit()は、コンポーネントがその初期データを取得するのに適した場所です。

ディレクティブのデータバインド入力プロパティは構築後まで設定されないことにも注意してください。これらのプロパティに基づいてディレクティブを初期化する必要がある場合、それは問題です。 ngOnInit()が実行されたときに設定されているでしょう。

NgOnChanges()メソッドはこれらのプロパティにアクセスする最初の機会です。 Angularは、ngOnInit()の前に何度もngOnChanges()を呼び出します。それは一度だけngOnInit()を呼び出します。

コンポーネントを作成したらすぐにAngularを使用してngOnInit()メソッドを呼び出すことができます。それが重い初期化ロジックが属するところです。

0

コンストラクタAngularのクラスコンストラクタは、主に依存関係を注入するために使用されます。 Angularは、このコンストラクター注入パターンを呼び出します。これについては、ここで詳しく説明します。より詳細なアーキテクチャの洞察については、MiškoHeveryによるConstructor InjectionとSetter Injectionの両方を読むことができます。

ただし、コンストラクターの使用法はDIに限定されません。たとえば、@ angular/routerモジュールのrouter-exitディレクティブは、それを使用して、ルーターエコシステム内の自分自身とその位置(viewContainerRef)を登録します。 @ViewChildクエリが評価される前に、ViewContainerRefを取得する方法を説明しました。

それでも、一般的な方法では、コンストラクタにできる限り少ないロジックを追加します。

NgOnInit AngularがngOnInitを呼び出したときに上で学んだように、コンポーネントDOMの作成を完了し、コンストラクタを通してすべての必要な依存関係を注入し、入力バインディングを処理しました。それで、ここであなたはそれが初期化ロジックを実行するのに良い場所になる利用可能なすべての必要な情報を持っています。

このロジックがDI、DOM、または入力バインディングに依存しない場合でも、ngOnInitを使用して初期化ロジックを実行するのが一般的な方法です。

0
arun thakur

Angularライフサイクル内

1)Angularインジェクタはコンストラクタパラメータを検出し、クラスをインスタンス化します。

2)次のアングルコールライフサイクル

Angularライフサイクルフック

ngOnChanges - >ディレクティブパラメータバインディングを呼び出す。

ngOnInit - >角度レンダリングを開始...

角度ライフサイクルの状態で他のメソッドを呼び出します。

0

constructorname__は、Angularがコンポーネントを「インスタンス化/構築」するときに呼び出されます。ngOnInitname__メソッドは、コンポーネントのライフサイクルの初期化部分を表すフックです。 サービスインジェクション :にのみ使用する

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

それが可能であっても、内部で「作業」をするべきではありません。コンポーネントの「初期化」で行わなければならないアクションを起動したい場合は、ngOnInitname__を使用します。

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

さらに、親コンポーネントから来る 入力プロパティ を含むアクションは、コンストラクタ内では実行できません。それらは、ngOnInitname__メソッドまたは別のフックに配置する必要があります。ビューに関連する要素(DOM)についても同じです。例えば、 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
};
0
veben

Constructorは、コンポーネント(または他のクラス)がビルドされるときに実行される関数です。

ngOnInitは、コンポーネントのライフサイクルメソッドグループに属する関数であり、コンポーネントの異なる瞬間に実行されます(そのため、ライフサイクルの名前が付けられています) 。それらすべてのリストを次に示します。

enter image description here コンストラクターは、ライフサイクル関数の前に実行されます。

0

constructor()は依存性注入をするために使われます。

ngOnInit()ngOnChanges()ngOnDestroy()などはライフサイクルメソッドです。 ngOnChanges()ngOnInit()より前に最初に呼び出されます。バインドされたプロパティの値が変更されたとき、変更がない場合は呼び出されません。 ngOnDestroy()はコンポーネントが削除されたときに呼び出されます。それを使うためには、OnDestroyはクラスによってimplementされる必要があります。

0
student