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


1075

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

ngOnInitすでに使用している場合、なぜ使用する必要がありconstructorますか?


11
ねえ、Angularの内部動作の観点からの違いを説明する私の答えをチェックしください
Max Koretskyi


1
@MaximKoretskyi、あなたのリンクは死んでいます。
Yash Capoor

回答:


1112

Constructorクラスがインスタンス化されるときに実行されるクラスのデフォルトの方法で、クラスのフィールドとそのサブクラスの適切な初期化を保証します。Angular、またはより優れたDependency Injector(DI)は、コンストラクターパラメーターを分析し、呼び出しによって新しいインスタンスを作成するときnew MyClass()に、コンストラクターパラメーターの型と一致するプロバイダーを見つけて解決し、次のようにコンストラクターに渡します

new MyClass(someArg);

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

それOnInitを使用するには、次のようにインポートする必要があります(実際に実装することOnInitは必須ではありませんが、適切な方法と見なされます)。

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

次に、makeメソッドを使用するには、次の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、すべての初期化/宣言に使用し、コンストラクターで機能するものを回避します。コンストラクターは、クラスメンバーの初期化にのみ使用する必要がありますが、実際の「作業」は行わないでください。

したがって、constructor()Dependency Injectionのセットアップに使用する必要があります。ngOnInit()は、「開始」するのにより適切な場所です。コンポーネントのバインディングが解決される場所/タイミングです。

詳細については、ここを参照してください。


62
正確には、ほとんど(またはすべて)のクラスベースの言語には、特に最終フィールド(TSにそれらがあるかどうかわからない)などの非常に難しい問題が発生する可能性がある他のクラスを拡張するクラスの適切な初期化順序を保証するためのコンストラクタがあります。コンストラクタはAngular2とは関係なく、TypeScriptの機能です。ライフサイクルフックは、初期化が行われた後、またはコンポーネントが特定の状況でコンポーネントを動作させ、適切なタイミングでタスクを実行する機会を与えるイベントが発生したときに、Angularによって呼び出されます。
ギュンターZöchbauer

13
angular.io/docs/ts/latest/guide/server-communication.htmlには、これを説明するブロック引用があります。「コンストラクターが単純で、すべての実際の作業(特に、リモートサーバー)は別の方法で処理されます。」-この場合、そのメソッドはngOnInit()です
yoonjesung 2017

3
Angularがコンポーネントの作成を完了したことを示すためにAngular2によって呼び出されるライフサイクルフックです。-それは正確ではありません。バインディングが初期化されたことを通知します。コンポーネントは以前に作成されています。私の答えを
Max Koretskyi 2017

22
すべての「ベストプラクティス」と同様に、コンストラクターで「作業」を行うべきではない理由についても説明することをお勧めします。Angularチームリーダーによるこの記事は濃密ですが、役立つ可能性があります:misko.hevery.com/code-reviewers-guide/… また、OnInitを実装するために必要な呪文(これは簡単に見つけることができます)の重要性を低くする必要があります。データバインディングがコンストラクターで使用できないという重要な事実。
レイキム2017年

2
tsconfig.jsonlike モードでstrictモードがtrueの場合、like ではなくで"strict": trueクラスメンバーを初期化する必要があります。constructorngOnitFormGroup
Rohit Sharma

174

記事は、角度でコンストラクタとngOnInitの本質的な違いは、複数の視点の違いを探ります。この回答は、コンポーネントの初期化プロセスに関連する最も重要な違いの説明を提供し、使用方法の違いも示しています。

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

  • コンポーネントツリーの構築
  • 変化検出の実行

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

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

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

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

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

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

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

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

初期化ロジックは、コンストラクターで、またはngOnInit必要なものに応じて実行できます。たとえば、「@ ViewChildクエリが評価される前にViewContainerRefを取得する方法は次のとおりです」という記事は、コンストラクターで実行する必要がある初期化ロジックのタイプを示しています

以下は、トピックをよりよく理解するのに役立つ記事です。


33
これは受け入れられる答えになるはずです。それは実際にマントラを繰り返して述べるのではなく、なぜその理由を説明しthe constructor should only be used to inject dependenciesます。
Stavm 2017

1
@ yannick1976、ありがとう!参照記事をチェックしてください
Max Koretskyi 2018

@flobacca、質問を言い換えてください。あなたが何を求めているのか理解するのは難しいです
Max Koretskyi

私が間違っている場合は修正してください。コンポーネントツリーが最初に作成され、次に検出プロセスが変更されることを理解しました。最初にAppComponentコンストラクターが呼び出され(解決された依存関係と共に)、次にChildComponentコンストラクターが(依存関係と共に)呼び出され、次にAppComponentの入力バインディングが呼び出され、次にOnInitが呼び出されます。しかし、私の懸念は、両方のコンポーネントにライフサイクルフックを追加した場合、フローはAppComponentConstructor —-> AppComponentOnInit —→ChildComponentConstructor —→ChildComponentOnInit ChildComponentConstructorの前にAppComponentOnInitが呼び出される理由
user2485435

1
@MaxKoretskyiakaWizard正解でした。アプリケーションのセットアップでいくつかの間違いをしました。それはあなたの説明どおりに機能しています。 angular-c7zjsx.stackblitz.io
user2485435

95

最良の例はサービスを使用することだと思います。コンポーネントが「アクティブ化」されたときにサーバーからデータを取得したいとします。サーバーからデータを取得した後、データにいくつか追加の処理を行いたいとしましょう。エラーが発生し、別の方法でログに記録したい場合があります。

コンストラクターを超える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();
    };


}

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


user_listをObservableに設定するだけで、例を簡略化できます。Angular2には非同期パイプがあるため、問題はありません。
DarkNeuron 2017

@Morgan、私がここで小さなことを学ぶためだけに、なぜ最初に関数getUsersを作成してからそれに関数を挿入するのngOnInitですか ngOnInitでそれを記述するだけのコードではありませんか?私はなぜ人々がこのようにそれをするのか疑問に思っていますか?必要に応じてコードを再利用できるようにするためですか?ありがとう。
Alfa Bravo

31
以下の答えに見られるように、これがコンストラクター内にある場合、違いはありません。これは目的に対する実際の答えではありません。
ジミー・ケイン

8
これがどのように質問に答えるかはわかりません。なぜコードを単に入れられなかったのconstructorですか?
CodyBugstein

1
@モーガン、なぜあなたはただできないのですかconstructor(private _userService: UserService){ this.getUsers(); };
アシュリー

82

OK、最初にすべてのngOnInit部分である角度ライフサイクルながら、constructorの一部であるES6主な違いはここから始まるので、JavaScriptクラス!...

Angularのライフサイクルを示す私が作成した以下のチャートを見てください。

ngOnInitとコンストラクタ

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

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

[OK]を、私はまた、我々はの使用を得る方法を見て、外観にあなたのためのサンプルコードを共有ngOnInitし、constructor以下のコードでは:

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

1
ありがとう。これが最良の答えです。
Don Dilanga

58

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

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

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

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

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


49

私は上記の説明にスキップされた一つの重要なものを追加し、時に説明しますMUST使用しますngOnInit

ViewChildrenContentChildrenElementRefなどを介してコンポーネントの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
  }
}

3
いいえ。以下のために@ViewChildren、特に、あなたが使用する必要があるngAfterViewInit方法を。ここを参照してください:stackoverflow.com/questions/46314734/...
AsGoodAsItGets

1
@AsGoodAsItGets、指摘してくれてありがとう。私は今答えを改善しました
ミロスラフジョナス

38

短くてシンプルな答えは、

Constructorconstructorは、コンポーネントが構築されているときのdefault methodデフォルトによる)実行です。an instanceクラスを作成すると、そのときにもconstructor(default method)呼び出されます。つまり、コンポーネント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フック

両方の実装を示すこの小さなデモを確認できます。


5
「コンストラクタは、コンポーネントが初期化されるときに実行または呼び出されるものだ」と私は思います。誤解を招くです。コンストラクタは、コンポーネントではなくクラスの機能です。クラスのインスタンスは、コンストラクターが呼び出され Angularが初期化した後にのみコンポーネントになると思います。
ギュンターZöchbauer

はい、今確認できるステートメントを変更しました。
micronyks 2016

1
うーん、私見それはまだ同じです。「コンストラクター(デフォルトのメソッド)は、コンポーネントが構築されるときに実行または呼び出されるものです。」コンポーネントが構築されたときだけでなく、サービスやコードのようなときにも呼び出さnew MyClass()れます。コンストラクタはコンポーネントに関するものであり、それらはクラスに関するものであり、これらのクラスのインスタンスを初期化するものであると言うのは誤解を招くと思います。コンポーネントはたまたまそのようなクラスです。そうでなければ私はそれが良い答えだと思います。
ギュンターZöchbauer

2
そのとおり。クラスのオブジェクトを作成すると、その時間constructorも呼び出されることを忘れていました。しかし、この答えはangular2のコンテキストで書かれています。最良の答えを知るには、OOPの基本を知っている必要があります。それでも答えを更新します。
micronyks 2016

@GünterZöchbauer、私はコンポーネントではなくクラスの機能である正しいアサーションであるとは思いません。はい、プログラミング言語の観点からは、これは正しいです。しかし、ライフサイクルフックがまったくなくても、コンポーネントを正常に処理できます。しかし、DIが必要な場合は、それが唯一の注入可能な場所であるため、コンストラクターなしでコンポーネントを操作することはできません。私の答えを
Max Koretskyi 2017

20

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

クラスレベルの変数

通常は、残りのコンポーネントで使用されるすべての変数をここで宣言します。値が他に依存しない場合は初期化するか、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フレームワークを使用していて、特定のライフサイクルイベントと対話する必要がある場合は、フレームワークが提供するメソッドを使用して問題を回避します。


19

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

18

コンストラクタの主な違いと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は、他のコンポーネントユニット(たとえば、一部のテンプレートロジック)を分離するために完全にスタブすることができます。

継承

子クラスは、コンストラクターを拡張することのみが可能で、それらを置き換えることはできません。

this以前super()は参照できないため、初期化の優先順位が制限されます。

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

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

これをコンストラクタだけで実装することは不可能です。


12

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

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

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

3)子供を作成する機能が必要だとしましょう。これが複雑でユーモラスにならないようにするには、人間のコンポーネントのライフのヤングアダルトステージでのみ関数を呼び出す必要があります。したがって、親コンポーネントがヤングアダルトステージにあるときにのみアクティブになるコンポーネントを開発します。フックは、そのライフステージに信号を送り、コンポーネントに作用させることで、そのために役立ちます。

楽しいもの。想像力を働かせて実際にこのようなものをコーディングすると、複雑で面白くなります。


7

コンストラクタは JavaScriptでの方法であり、クラスはそれが直ちにそれが角フレームワークで使用されているか否かをコンストラクタを実行していないか、JavaScriptエンジンによって呼び出されnot.Soおよび角度は全く有してインスタンス化され.When ES6におけるクラスの特徴として考えられていますそれを制御します。

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がコンポーネントの初期化を完了したときにAngular.ngOnInitレンダリングにngOnInitライフサイクルフックがある理由です。

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は依存関係のタイプを取得するのに役立ち、コンストラクターで定義され、最後に特定のコンポーネントで使用したい依存関係の種類。


7

ここで注意すべき2つの点:

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

どちらも使い勝手が異なります。


5

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

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

つまり:

コンストラクタ()-->ngOnChanges()-->ngOnInit()

上記のようngOnChanges()に、入力または出力バインディング値が変更されたときに呼び出されます。


4

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

onInit()メソッド(角度の概念)のタスクは、正しいオブジェクト(表現不変)でのメソッド呼び出しを許可することです。各メソッドは、メソッドが終了したときに表現不変式が保持されることを確認する必要があります。

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


4

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

コンストラクターはJavaScriptエンジンによって初期化されるため、TypeScriptを使用すると、特定のプロパティに対してマップする必要がある依存関係をAngularに指示できます。

ngOnInitは純粋に、Angularがコンポーネントの初期化を完了したことを示す信号を提供するためのものです。

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

このため、@ Input()プロパティはngOnInit内で使用できますが、設計ではコンストラクタ内で定義されていません


2

コンストラクタが最初で、@ inputデータがnullの場合に発生することがあります。したがって、サービスを宣言するためにコンストラクターを使用し、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

Angularのライフサイクル

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

2)次の角度呼び出しのライフサイクル

Angular Lifecycle Hooks

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

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

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


1

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

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

たとえそれが可能であっても、内部で「作業」を行うべきではありません。コンポーネントの「初期化」で発生する必要があるアクションを起動する場合は、次を使用しますngOnInit

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

さらに、親コンポーネントからの入力プロパティを含むアクションは、コンストラクターでは実行できません。ngOnInitメソッドまたは別のフックに配置する必要があります。これは、ビューに関連する要素(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

constructor() 依存性注入を行うために使用されます。

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


1
同意します、これは短くて明確です。たとえば、constructor()はサービスオブジェクトを追加するためのものであり、ngOnInit()は必要なサービス関数呼び出しでコンポーネントを操作するためのものです。
Steve

0

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

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

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

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

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

  • 一般に、コンストラクターではなくngOnInit()でのサービスの呼び出し

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


0

コンストラクタ

コンストラクター関数はすべてのクラスに付属しています。コンストラクターはAngularに固有ではなく、オブジェクト指向の設計から派生した概念です。コンストラクタは、コンポーネントクラスのインスタンスを作成します。

OnInit

このngOnInit関数は、Angularコンポーネントのライフサイクルメソッドの1つです。Angularコンポーネントのライフサイクルメソッド(またはフック)を使用すると、コンポーネントのライフのさまざまな段階でコードを実行できます。コンストラクターメソッドとは異なり、ngOnInitメソッドは、OnInitこのメソッドを使用するためにコンポーネントが実装する必要があるAngularインターフェイス()から取得されます。このngOnInitメソッドは、コンポーネントが作成された直後に呼び出されます。


0

コンストラクタは、クラスがインスタンス化されるときに実行されます。角度には関係ありません。これはJavascriptの機能であり、Angularはそれを制御できません

ngOnInitはAngular固有であり、Angularがすべての入力プロパティでコンポーネントを初期化したときに呼び出されます

@Inputプロパティは、ngOnInitライフサイクルフックの下で使用できます。これは、バックエンドサーバーからデータを取得してビューに表示するなど、いくつかの初期化を行うのに役立ちます

@Inputプロパティがコンストラクター内で未定義として表示される


-1

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

ngOnInitはコンポーネントのライフサイクルメソッドグループに属する関数であり、コンポーネントの別の瞬間に実行されます(それがライフサイクルの名前です)。ここにそれらすべてのリストがあります:

ここに画像の説明を入力してください コンストラクターは、ライフサイクル関数の前に実行されます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.