通常、NGで命令を使用する場合、ほとんどの場合に使用するリンク関数はリンク属性です。次の記事では、コンプリ、プレリンク、およびリンク後の使用と違いを説明します。
Angularjsの指示は非常に魔法のようで、非常にセマンティックで非常に再利用可能なコンポーネントを作成できます。これは、Webコンポーネントの先駆者として理解できます。
インターネット上には、指示の使用方法を紹介する多くの記事や関連する本があります。それらを比較すると、コンパイルとリンクの違いを紹介することはめったにありません。リンク前とリンク後はもちろんです。
ほとんどのチュートリアルでは、コンパイルがNG内で使用されると言うだけで、リンク属性のみを使用することをお勧めします。これは、ほとんどの指示の場合です。
これらの機能の違いを正しく理解することで、NGの内部実行メカニズムの理解が向上し、より良いカスタム命令の開発に役立つため、これは非常に残念です。
だから私に従って、これらの機能が何であるか、いつ使用すべきかを理解するために、次のコンテンツを段階的に見てください
この記事では、指示について特定の理解があると想定しています。そうでない場合は、この記事を読むことを強くお勧めします。
ngで手順を処理する方法
分析を開始する前に、Ng-Chineseが指示をどのように処理するかを見てみましょう。
ブラウザがページをレンダリングすると、基本的にHTMLアイデンティティを読み取り、DOMノードを作成し、DOMツリーが作成された後にイベントをブロードキャストします。
スクリプトタグを使用してページにNGアプリケーションコードをロードすると、NGは上記のDOM完了イベントを聴き、NG-APP属性を持つ要素を見つけます。
そのような要素を見つけた後、NGはこの要素の開始点でDOMの処理を開始するため、NG-APPがHTML要素に追加された場合、NGはHTML要素でDOMの処理を開始します。
この出発点から始めて、NGはすべての子要素を再帰的に検索し始めます。これは、アプリケーションで定義されている命令ルールに準拠しています。
NGの指示に対処する方法は、実際に定義するオブジェクトプロパティに依存します。コンパイルまたはリンク関数を定義するか、リンクの代わりにリンク前およびリンク後の機能を使用できます。
では、これらの関数の違いは何ですか?なぜそれを使うのですか?そしていつ?
これらの質問で、これらの謎に答えるために私に段階的にフォローしてください
コードの一部
これらの機能の違いを説明するために、以下のシンプルでわかりやすい例を使用します
1.ご質問がある場合は、以下にコメントを追加することをheしないでください。
次のHTMLタグコードをご覧ください
コードコピーは次のとおりです。
<level-one>
<レベルツー>
<Level-Three>
こんにちは
</level-three>
</revel-two>
</level-one>
次に、JSコードの一部があります
コードコピーは次のとおりです。
var app = angular.module( 'plunker'、[]);
関数createdirective(name){
return function(){
戻る {
制限: 'e'、
コンパイル:function(telem、tattrs){
console.log(name + ':compile');
戻る {
pre:function(scope、ielem、iattrs){
console.log(name + ':pre link');
}、
投稿:function(scope、ielem、iattrs){
console.log(name + ':post link');
}
}
}
}
}
}
app.directive( 'levelone'、createdirective( 'lethone'));
app.directive( 'leveltwo'、createdirective( 'leveltwo'));
app.directive( 'levelthree'、createdirective( 'levelthree'));
結果は非常に単純です。NGが3つのネストされた命令を処理し、各命令には独自の複雑、リンク、およびリンク後の機能があります。各関数は、コンソールに線を印刷して、それ自体を識別します。
この例を使用すると、手順を処理する際にNGの内部プロセスを簡単に理解できます
コード出力
以下は、コンソールの出力結果のスクリーンショットです
この例を自分で試してみたい場合は、このPLNKRをクリックして、コンソールの結果を表示してください。
分析コード
最初に注意すべきことは、これらの関数の呼び出しの順序です。
コードコピーは次のとおりです。
//フェーズをコンパイルします
// levelone:コンパイル関数が呼び出されます
// leveltwo:コンパイル関数が呼び出されます
// levelthree:コンパイル関数が呼び出されます
//プレリンクフェーズ
// levelone:リンク前の関数が呼び出されます
// leveltwo:リンク前の関数が呼び出されます
// levelthree:リンク前の関数が呼び出されます
//リンク後フェーズ(逆注文に注意)
// levelthree:投稿リンク関数が呼び出されます
// leveltwo:投稿リンク関数が呼び出されます
// levelOne:リンクのポスト関数が呼び出されます
この例は、NGがリンクの前にすべての命令をコンパイルし、リンクがプレリンクとリンク後の段階に分割されることを明確に示しています。
コンパイルとプレリンクの実行順序は順次実行されることに注意してくださいが、リンク後はまったく逆です。
したがって、上記は異なる段階を明確に特定していますが、コンパイルとプレリンクの違いは何ですか?どちらも同じ実行順序であるので、なぜそれらを2つの異なる機能に分割する必要があるのですか?
dom
より深く掘り下げるために、上記のコードを単純に変更しましょう。これにより、各関数のパラメーターリストに要素変数も印刷します。
コードコピーは次のとおりです。
var app = angular.module( 'plunker'、[]);
関数createdirective(name){
return function(){
戻る {
制限: 'e'、
コンパイル:function(telem、tattrs){
console.log(name + ':compile =>' + telem.html());
戻る {
pre:function(scope、ielem、iattrs){
console.log(name + ':pre link =>' + ielem.html());
}、
投稿:function(scope、ielem、iattrs){
console.log(name + ':post link =>' + ielem.html());
}
}
}
}
}
}
app.directive( 'levelone'、createdirective( 'lethone'));
app.directive( 'leveltwo'、createdirective( 'leveltwo'));
app.directive( 'levelthree'、createdirective( 'levelthree'));
Console.logの出力に注意してください。ただし、元のHTMLタグの出力を除き、基本的に他の変更はありません。
これは、これらの機能のコンテキストの理解を深めるはずです。
もう一度コードを実行して表示します
出力
以下は、コンソールの出力結果のスクリーンショットです
それでも効果を確認して自分で実行したい場合は、このPLNKRをクリックしてから、コンソールで出力結果を表示できます。
観察する
DOM結果の出力は、いくつかの興味深いものを公開する可能性があります:DOMコンテンツは2つの関数コンパイルとプレリンクで異なります
では、何が起こったのでしょうか?
コンパイル
NgがDOMビルドが完了していることがわかったとき、DOMの処理を開始することをすでに知っています。
したがって、NgがDOMを通過しているとき、彼はレベル1の要素に遭遇し、その定義からいくつかの必要な機能を実行する必要があることを学びます
コンパイル関数はレベル1命令の命令オブジェクトで定義されているため、呼び出され、そのパラメーターとして要素オブジェクトを渡します
よく見ると、ブラウザがこの要素オブジェクトを作成すると、それが依然として最も元のHTMLタグであることがわかります。
1。ngでは、元のDOMは通常、テンプレート要素を識別するために使用されるため、コンパイル関数パラメーターを定義するときにテレム名を使用し、この変数はテンプレート要素を指します。
LevelONE命令のコンパイル関数が実行されると、NGはDOMノードを深く再帰的に通過し、レベル2およびレベル3でこれらの操作を繰り返します。
リンク後
リンク前関数に入る前に、リンク後の関数を見てみましょう。
2。命令を定義するときに1つのリンク関数のみを使用する場合、NGはこの関数をリンクとして扱うため、最初にこの関数を議論する必要があります。
NgがすべてのDOMを通過し、すべてのコンパイル関数を実行した後、関連するリンク後の関数が逆に呼び出されます。
DOMは、リンク後の関数を逆転させ始め、実行します。したがって、このリバースコールは以前に少し奇妙に思えましたが、実際にそうすることは理にかなっています。
サブインストラクションを含むリンク後の命令を実行するとき、リバースリンク後のルールは、サブインストラクションのリンクが実行されていることを確認できます。
したがって、レベルワン命令のリンク後関数を実行するとき、レベル2とレベル3のポストリンクが実際に実行されていることを確認できます。
これが、リンク後のものがビジネスロジックを書くための最も安全な場所またはデフォルトの場所であると人々が考える理由です。
しかし、なぜここの要素がコンパイルの要素と違うのですか?
ngが命令のコンパイル関数を呼び出すと、テンプレート要素の要素インスタンスオブジェクトが作成され、スコープオブジェクトが提供されます。このスコープは、新しいインスタンスであるか、すでに存在する可能性があります。サブスコープである場合もあれば、独立したスコープである場合もあります。これらはすべて、命令定義オブジェクトのスコープ属性値に依存します。
したがって、リンクが発生すると、このインスタンス要素とスコープオブジェクトは既に利用可能であり、ngによってパラメーターとしてリンク後関数のパラメーターリストに渡されます。
1.私は個人的にIELEM名を使用してリンク関数のパラメーターを定義し、要素インスタンスを指します
したがって、ポストリンク(リンク)関数の要素パラメーターオブジェクトは、テンプレート要素の代わりに要素インスタンスです。
したがって、上記の例の出力は異なります
リンク前
リンク後関数を書くときは、リンク後の関数を実行するときに、すべての子供の指示のリンク後機能が実行されていることを確認できます。
ほとんどの場合、それはより良いことができるので、通常、それを使用して命令コードを書きます。
ただし、NGは追加のフックメカニズム、つまりプレリンク関数を提供します。これにより、すべてのサブインストラクションのリンク後関数を実行する前に、他のコードが実行されることが保証されます。
この文は繰り返し考慮に値します
リンク前の関数は、要素インスタンスで、およびサブインストラクションのリンクが実行される前に実行されることを保証できます。
したがって、リンク後の関数を逆転させることは理にかなっており、元の順序でリンク前関数を実行します。
これはまた、リンク前関数がすべてのサブインストラクションのリンク前関数の前に実行されることを意味するため、完全な理由は次のとおりです。
要素のリンク前関数は、すべてのサブインストラクションのリンクとプレリンクが実行される前に実行されることが保証されます。以下の図を参照してください。
レビュー
上記の元の出力を振り返ると、何が起こっているのかを明確に認識できます。
コードコピーは次のとおりです。
//ここで要素はまだ元のテンプレート要素です
//フェーズをコンパイルします
// levelone:コンパイル関数は元のdomで呼び出されます
// leveltwo:コンパイル関数は元のdomで呼び出されます
// levelthree:コンパイル関数は元のdomで呼び出されます
//ここで、要素はインスタンス化されており、
//スコープにバインドされています
//(たとえば、ng-repeatには複数のインスタンスがあります)
//プレリンクフェーズ
// levelone:リンク前の関数は要素インスタンスで呼び出されます
// leveltwo:事前リンク関数は要素インスタンスで呼び出されます
// levelthree:リンク前の関数は要素インスタンスで呼び出されます
//リンク後フェーズ(逆注文に注意)
// levelthree:投稿リンク関数は要素インスタンスで呼び出されます
// leveltwo:投稿リンク関数は要素インスタンスで呼び出されます
// levelone:投稿リンク関数は要素インスタンスで呼び出されます
まとめ
上記の分析を振り返ってみると、これらの機能の違いと使用法について説明できます。
関数をコンパイルします
コンパイル関数を使用して、元のDOMインスタンスとスコープインスタンスを作成する前に、元のDOM(テンプレート要素)を変更します。
複数の要素インスタンスを生成する必要があり、テンプレート要素が1つしかない状況に適用できます。 Ng-Reepeatが最良の例です。コンパイル関数ステージの元のDOMを変更して複数の元のDOMノードを生成し、それぞれ要素インスタンスを生成します。コンパイルは1回しか実行されないため、複数の要素インスタンスを生成する必要がある場合にパフォーマンスを向上させることができます。
テンプレート要素と関連属性はコンパイル関数のパラメーターとして渡されますが、現時点ではスコープは使用できません。
これが機能です。
コードコピーは次のとおりです。
/**
*関数をコンパイルします
*
* @Param Telem-テンプレート要素
* @param tattrs-テンプレート要素の属性
*/
function(Telem、Tattrs){
// ...
};
リンク前機能
Pre-Link関数を使用して、NGがコンパイル関数を実行した後にビジネスコードを実行しますが、すべてのサブインストラクションのリンク後関数が実行される前に実行されます。
スコープオブジェクトと要素インスタンスは、リンク前関数のパラメーターとして渡されます。
これが機能です。
コードコピーは次のとおりです。
/**
*プレリンク機能
*
* @paramスコープ - このイスタンスに関連するスコープ
* @Param IELEM-インスタンス要素
* @param Iattrs-インスタンス要素の属性
*/
function(scope、ielem、iattrs){
// ...
};
リンク後機能
リンク後関数を使用して、ビジネスロジックを実行します。この段階では、すべてのサブインストラクションが編集されており、リンク前およびリンク後の機能が実行されていることがすでにわかっています。
これは、最も安全でデフォルトの執筆ビジネスロジックコードと見なされるものです。
スコープインスタンスと要素インスタンスは、リンク後関数のパラメーターとして渡されます。
これが機能です。
コードコピーは次のとおりです。
/**
*リンク後機能
*
* @paramスコープ - このイスタンスに関連するスコープ
* @Param IELEM-インスタンス要素
* @param Iattrs-インスタンス要素の属性
*/
function(scope、ielem、iattrs){
// ...
};
要約します
これで、コンパイル、プレリンク、リンク、およびこの機能の違いを明確に理解する必要があります。
あなたがまだ持っていない、そしてあなたが真剣なNG開発者であるならば、あなたがそれを理解するまでこの記事をもう一度読むことを強くお勧めします
これらの概念を理解することは非常に重要です。これは、ネイティブの指示がどのように機能するかを理解するのに役立ち、独自のカスタム命令を最適化するのにも役立ちます。
ご質問がある場合は、以下のコメントに質問を追加してください
将来的には、指示に関する他の2つの質問を引き続き分析します。
1. DirectiveはTransClusion属性をどのように機能させますか?
2。命令のコントローラー機能はどのように関連していますか?
最後に、この記事で何か問題がある場合は、時間内にコメントしてください
ありがとう!