Angular 2 Directive Lifecycle
11161 ワード
Angular 2 Directive Lifecycle(ライフサイクル)について説明する前に、Angular 2のDirective(コマンド)とComponent(コンポーネント)の関係について説明します.
Angular 2で定義された命令とコンポーネントインタフェースを見てみましょう.
上の図とAngular 2の命令とコンポーネントのインタフェース定義を観察することで、命令とコンポーネントの関係をまとめることができます.コンポーネントは命令に継承され、template、styles、animations、encapsulationなどのUIビューに関連する属性が拡張されます.
次に本題に入り、作成、適用、破棄の手順を記録するAngular 2コマンドのライフサイクルについて説明します.Angular 2は、命令ライフサイクルに関連する一連のフックを提供し、命令ライフサイクルの変化を監視し、関連する操作を実行するのに便利である.Angular 2のすべてのフックを下図に示します.
どうしてそんなにフックが多いのか、驚いたのではないでしょうか.大丈夫です.命令とコンポーネントの違いに基づいてクラスを分けます.命令アセンブリと共有するフック ngOnChanges ngOnInit ngDoCheck ngOnDestroy
アセンブリ特有のフック ngAfterContentInit ngAfterContentChecked ngAfterViewInit ngAfterViewChecked
Angular 2指令ライフサイクルフックの役割と呼び出し順序 ngOnChanges-データバインディング入力属性の値が変化すると が呼び出される. ngOnInit-最初のngOnChangesの後に を呼び出す. ngDoCheck-カスタムメソッド、値の変更を検出および処理するための ngAfterContentInit-コンポーネントコンテンツの初期化後に を呼び出す. ngAfterContentChecked-コンポーネントは、コンテンツをチェックするたびに を呼び出す. ngAfterViewInit-コンポーネントの対応するビューが初期化された後、 が呼び出される. ngAfterViewChecked-コンポーネントはビューをチェックするたびに を呼び出す. ngOnDestroy-命令破棄前に を呼び出す
Angular 2指令ライフサイクルフック詳細
命令ライフサイクルフックについて詳しく説明する前に、コンストラクション関数について説明します.
constructor
コンポーネントのコンストラクション関数は、すべてのライフサイクルフックの前に呼び出され、主に注入に依存したり、簡単なデータ初期化操作を実行したりするために使用されます.
ngOnChanges
データバインディング入力属性の値が変化すると、AngularはngOnChangesメソッドをアクティブに呼び出します.コンポーネントの入力プロパティの変化を監視するために主に使用される、バインドされたプロパティの新しい値と古い値を含むSimpleChangesオブジェクトが得られます.
app.component.ts
child.component.ts
以上のコードの実行後、ブラウザの出力結果:
ngOnInit
1回目のngOnChanges実行後に呼び出され、1回のみ呼び出されます.主に、コンポーネントの他の初期化操作を実行したり、コンポーネントが入力した属性値を取得したりするために使用されます.
ngOnDestory
命令が破棄される前に、ngOnDestoryメソッドが呼び出されます.イベントリスニングの削除、タイマのクリア、Observableのキャンセルなど、主にクリーンアップ操作を実行するために使用されます.
ngDoCheck
コンポーネントの入力プロパティが変化すると、ngDoCheckメソッドがトリガーされます.この方法を使用して、検出ロジックをカスタマイズできます.私たちの変化検出の速度を加速させるためにも使用できます.
ngAfterContentInit
コンポーネントが
使用例については、「Angular 2 ContentChild&ContentChildren」を参照してください.
ngAfterContentChecked
コンポーネントが
ngAfterViewInit
コンポーネントの対応するビューが初期化された後に呼び出され、主に@ViewChildまたは@ViewChildrenプロパティエクスプローラでクエリーされたビュー要素を取得するために使用されます.
使用例については、「Angular 2 ViewChild&ViewChildren」を参照してください.
ngAfterViewChecked
コンポーネントがビューをチェックするたびに呼び出されます
Angular 2 LifecycleHooks、SimpleChangesなどの関連インタフェース
LifecycleHooksインタフェース
SimpleChange
SimpleChanges
Angular 2 Viewの詳細
Angular 2のビューは、次の3つのセクションで構成されています. Elements-要素 Bindings-バインド Events-イベント Angular 2 TemplateRef&ViewContainerRefの記事では、Angular 2がサポートするView(ビュー)タイプについて説明します. Embedded Views-Template要素 Host Views-Componentコンポーネント 次に、コンポーネントに対応するHost Viewsを分析します.具体的な例は次のとおりです.
child.component.ts
app.component.ts
以上のコードの実行後、ブラウザの出力結果:
次にChildComponentコンポーネントを分析し、まずコンパイル後のcomponentを見てみましょう.ngfactory.jsファイル.
ChildComponent/component.ngfactory.jsコードクリップ:
ChildComponent/wrapper.ngfactory.jsコードクリップ:
話があるんだ
1.命令ライフサイクルフックを登録する場合、必ず対応するインタフェースを実現しますか?
命令ライフサイクルフックを登録する場合、対応するインタフェースを実現する必要はありません.インタフェースは、ライフサイクルフックを登録するときに、フックの名前を書き間違え、実行時に異常を投げ出さない可能性がありますが、ページ表示は予想される効果ではありません.そのため、読者はやはりこの開発規範を守ることをお勧めします.また、TypeScriptで定義されているインタフェースは、ES 5関連コードの生成をコンパイルせず、コンパイルフェーズの検証にのみ使用されることに注意してください.
未完待機
Angular 2で定義された命令とコンポーネントインタフェースを見てみましょう.
// angular2/packages/core/src/metadata/directives.ts
export interface Directive {
selector?: string; // HTML
inputs?: string[]; //
outputs?: string[]; //
host?: {[key: string]: string}; // 、
providers?: Provider[]; //
exportAs?: string; // ,
queries?: {[key: string]: any}; //
}
export interface Component extends Directive {
changeDetection?: ChangeDetectionStrategy; //
viewProviders?: Provider[]; // ( ContentChildren)
moduleId?: string; // id,
templateUrl?: string; // URL
template?: string; //
styleUrls?: string[]; //
styles?: string[]; //
animations?: any[]; //
encapsulation?: ViewEncapsulation; //
interpolation?: [string, string]; // , "{{" "}}"
entryComponents?: Array|any[]>; //
}
上の図とAngular 2の命令とコンポーネントのインタフェース定義を観察することで、命令とコンポーネントの関係をまとめることができます.コンポーネントは命令に継承され、template、styles、animations、encapsulationなどのUIビューに関連する属性が拡張されます.
次に本題に入り、作成、適用、破棄の手順を記録するAngular 2コマンドのライフサイクルについて説明します.Angular 2は、命令ライフサイクルに関連する一連のフックを提供し、命令ライフサイクルの変化を監視し、関連する操作を実行するのに便利である.Angular 2のすべてのフックを下図に示します.
どうしてそんなにフックが多いのか、驚いたのではないでしょうか.大丈夫です.命令とコンポーネントの違いに基づいてクラスを分けます.
Angular 2指令ライフサイクルフックの役割と呼び出し順序
Angular 2指令ライフサイクルフック詳細
命令ライフサイクルフックについて詳しく説明する前に、コンストラクション関数について説明します.
constructor
コンポーネントのコンストラクション関数は、すべてのライフサイクルフックの前に呼び出され、主に注入に依存したり、簡単なデータ初期化操作を実行したりするために使用されます.
import { Component, ElementRef } from '@angular/core';
@Component({
selector: 'my-app',
template: `
Welcome to Angular World
Hello {{name}}
`,
})
export class AppComponent {
name: string = '';
constructor(public elementRef: ElementRef) { //
this.name = 'Semlinker'; //
}
}
ngOnChanges
データバインディング入力属性の値が変化すると、AngularはngOnChangesメソッドをアクティブに呼び出します.コンポーネントの入力プロパティの変化を監視するために主に使用される、バインドされたプロパティの新しい値と古い値を含むSimpleChangesオブジェクトが得られます.
app.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'my-app',
template: `
Welcome to Angular World
`,
})
export class AppComponent { }
child.component.ts
import { Component, Input, SimpleChanges, OnChanges } from '@angular/core';
@Component({
selector: 'exe-child',
template: `
Child Component
{{ name }}
`
})
export class ChildComponent implements OnChanges{
@Input()
name: string;
ngOnChanges(changes: SimpleChanges) {
console.dir(changes);
}
}
以上のコードの実行後、ブラウザの出力結果:
ngOnInit
1回目のngOnChanges実行後に呼び出され、1回のみ呼び出されます.主に、コンポーネントの他の初期化操作を実行したり、コンポーネントが入力した属性値を取得したりするために使用されます.
import { Component, Input, OnInit } from '@angular/core';
@Component({
selector: 'exe-child',
template: `
:{{pname}}
`
})
export class ChildComponent implements OnInit {
@Input()
pname: string; //
constructor() {
console.log('ChildComponent constructor', this.pname); // Output:undefined
}
ngOnInit() {
console.log('ChildComponent ngOnInit', this.pname); // output: pname
}
}
ngOnDestory
命令が破棄される前に、ngOnDestoryメソッドが呼び出されます.イベントリスニングの削除、タイマのクリア、Observableのキャンセルなど、主にクリーンアップ操作を実行するために使用されます.
@Directive({
selector: '[destroyDirective]'
})
export class OnDestroyDirective implements OnDestroy {
sayHello: number;
constructor() {
this.sayHiya = window.setInterval(() => console.log('hello'), 1000);
}
ngOnDestroy() {
window.clearInterval(this.sayHiya);
}
}
ngDoCheck
コンポーネントの入力プロパティが変化すると、ngDoCheckメソッドがトリガーされます.この方法を使用して、検出ロジックをカスタマイズできます.私たちの変化検出の速度を加速させるためにも使用できます.
ngAfterContentInit
コンポーネントが
ng-content
命令を使用する場合、Angularは外部コンテンツをビューに配置した後に使用します.主に、@ContentChildまたは@ContentChildrenプロパティエクスプローラでクエリーされたコンテンツビュー要素を取得するために使用されます.使用例については、「Angular 2 ContentChild&ContentChildren」を参照してください.
ngAfterContentChecked
コンポーネントが
ng-content
命令を使用する場合、Angularは、外部コンテンツのバインディングが検出されるか、または変化するたびに呼び出される.ngAfterViewInit
コンポーネントの対応するビューが初期化された後に呼び出され、主に@ViewChildまたは@ViewChildrenプロパティエクスプローラでクエリーされたビュー要素を取得するために使用されます.
使用例については、「Angular 2 ViewChild&ViewChildren」を参照してください.
ngAfterViewChecked
コンポーネントがビューをチェックするたびに呼び出されます
Angular 2 LifecycleHooks、SimpleChangesなどの関連インタフェース
LifecycleHooksインタフェース
export interface OnChanges { ngOnChanges(changes: SimpleChanges): void; }
export interface OnInit { ngOnInit(): void; }
export interface DoCheck { ngDoCheck(): void; }
export interface OnDestroy { ngOnDestroy(): void; }
export interface AfterContentInit { ngAfterContentInit(): void; }
export interface AfterContentChecked { ngAfterContentChecked(): void; }
export interface AfterViewInit { ngAfterViewInit(): void; }
export interface AfterViewChecked { ngAfterViewChecked(): void; }
SimpleChange
//
export class SimpleChange {
constructor(public previousValue: any,
public currentValue: any,
public firstChange: boolean) {}
//
isFirstChange(): boolean { return this.firstChange; }
}
SimpleChanges
export interface SimpleChanges { [propName: string]: SimpleChange; }
Angular 2 Viewの詳細
Angular 2のビューは、次の3つのセクションで構成されています.
child.component.ts
import { Component, Input, SimpleChanges, OnChanges, AfterViewChecked } from '@angular/core';
@Component({
selector: 'exe-child',
template: `
Child Component
{{ name }}
`
})
export class ChildComponent implements OnChanges, AfterViewChecked{
@Input()
name: string;
ngOnChanges(changes: SimpleChanges) {
console.dir(changes);
setTimeout(() => {
this.name = 'exe-child-component-1'
}, 0);
}
ngAfterViewChecked() {
console.log('ngAfterViewChecked hook has been called');
}
}
app.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'my-app',
template: `
Welcome to Angular World
`,
})
export class AppComponent { }
以上のコードの実行後、ブラウザの出力結果:
次にChildComponentコンポーネントを分析し、まずコンパイル後のcomponentを見てみましょう.ngfactory.jsファイル.
ChildComponent/component.ngfactory.jsコードクリップ:
function View_ChildComponent0(viewUtils,parentView,parentIndex,parentElement) {
var self = this;
...
self._expr_7 = jit_CD_INIT_VALUE5;
}
/*
*
* ChildComponent - template
* Child Component
* {{ name }}
*/
View_ChildComponent0.prototype.createInternal = function(rootSelector) {
var self = this;
var parentRenderNode = self.renderer.createViewRoot(self.parentElement);
...
// (1) p - Child Component
self._el_1 = jit_createRenderElement6(self.renderer,parentRenderNode,
'p', jit__object_Object_7,self.debug(1,1,6));
// , - 'Child Component'
self._text_2 = self.renderer.createText(self._el_1,'Child Component',
self.debug(2,1,9));
// (2) p - {{ name }}
self._el_4 = jit_createRenderElement6(self.renderer,parentRenderNode,
'p', jit__object_Object_7,self.debug(4,2,6));
self._text_5 = self.renderer.createText(self._el_4,'',self.debug(5,2,9));
self.init(null,(self.renderer.directRenderer? null: [...]
),null);
return null;
};
//
View_ChildComponent0.prototype.detectChangesInternal = function(throwOnChange) {
var self = this;
self.debug(5,2,9);
var currVal_7 = jit_inlineInterpolate8(1,'',self.context.name,'');
if (jit_checkBinding9(throwOnChange,self._expr_7,currVal_7)) {
self.renderer.setText(self._text_5,currVal_7);
self._expr_7 = currVal_7;
}
};
ChildComponent/wrapper.ngfactory.jsコードクリップ:
function Wrapper_ChildComponent() {
var self = this;
self._changed = false;
self._changes = {}; // Changes
self.context = new jit_ChildComponent0();
self._expr_0 = jit_CD_INIT_VALUE1; // {}
}
Wrapper_ChildComponent.prototype.ngOnDestroy = function() { };
Wrapper_ChildComponent.prototype.check_name =function(currValue,
throwOnChange, forceUpdate) {
var self = this;
// ,jit_checkBinding2 looseIdentical(oldValue, newValue)
// (===)
if ((forceUpdate || jit_checkBinding2(throwOnChange,self._expr_0,currValue))) {
self._changed = true;
self.context.name = currValue;
// name SimpleChange
self._changes['name'] = new jit_SimpleChange3(self._expr_0,currValue);
self._expr_0 = currValue;
}
};
Wrapper_ChildComponent.prototype.ngDoCheck = function(view,el,throwOnChange) {
var self = this;
var changed = self._changed;
self._changed = false;
if (!throwOnChange) { if (changed) {
self.context.ngOnChanges(self._changes);
jit_setBindingDebugInfoForChanges4(view.renderer,el,self._changes);
self._changes = {};
} }
return changed;
};
...
return Wrapper_ChildComponent
})
話があるんだ
1.命令ライフサイクルフックを登録する場合、必ず対応するインタフェースを実現しますか?
命令ライフサイクルフックを登録する場合、対応するインタフェースを実現する必要はありません.インタフェースは、ライフサイクルフックを登録するときに、フックの名前を書き間違え、実行時に異常を投げ出さない可能性がありますが、ページ表示は予想される効果ではありません.そのため、読者はやはりこの開発規範を守ることをお勧めします.また、TypeScriptで定義されているインタフェースは、ES 5関連コードの生成をコンパイルせず、コンパイルフェーズの検証にのみ使用されることに注意してください.
未完待機