JavaScriptの急速な成長に伴い フルスタック 言語、ますます多くのアプリケーションが、Webブラウザーがデータバインディング、データビューの管理、データの変換、その他の多くのサービスなど、より多くのUI処理を処理できるようにするフレームワークを利用しています。最も有能で拡張可能で人気のあるフレームワークの1つは AngularJS 、およびAngularJSフレームワークの最も有用なコンポーネントの1つは、 指令 。 AngularJSは多くの便利なディレクティブを提供し、さらに重要なことに、カスタムディレクティブを作成するための豊富なフレームワークを提供します。
指令とは何ですか?簡単に言うと、ディレクティブは、HTMLDOM要素を操作して動作を追加するJavaScript関数です。ディレクティブは、非常に単純な場合もあれば、非常に複雑な場合もあります。したがって、それらを操作する多くのオプションと機能をしっかりと把握することが重要です。
このチュートリアルでは、ディレクティブとして実行される4つの関数が作成され、DOMに適用され、例が提供されます。この投稿は、AngularJSとカスタムディレクティブにある程度精通していることを前提としています。 Angularを初めて使用する場合は、 最初のAngularJSアプリの構築に関するチュートリアル。
構成できるオプションは多数あり、それらのオプションが互いにどのように関連しているかが重要です。各ディレクティブは、AngularJSがDOMをコンパイルしてリンクするときに、ライフサイクルに似たものを実行します。ディレクティブのライフサイクルは、ページがレンダリングされる前に、AngularJSブートストラッププロセス内で開始および終了します。ディレクティブのライフサイクルには、定義されている場合に実行できる4つの異なる関数があります。それぞれにより、開発者はライフサイクルのさまざまな時点でディレクティブを制御およびカスタマイズできます。
4つの機能は次のとおりです。 コンパイル 、 コントローラ 、 プレリンク そして ポストリンク 。
ザ・ コンパイル 関数を使用すると、ディレクティブはコンパイルおよびリンクされる前にDOMを操作できるため、ディレクティブを追加/削除/変更したり、他のDOM要素を追加/削除/変更したりできます。
ザ・ コントローラ 機能は、ディレクティブ通信を容易にします。兄弟および子ディレクティブは、兄弟および親のコントローラーに情報の伝達を要求できます。
ザ・ プレリンク 機能はプライベートを可能にします $ scope リンク後のプロセスが始まる前の操作。
ブラックベリー会社に何が起こったのか
ザ・ ポストリンク methodは、ディレクティブの主要な主力メソッドです。
ディレクティブでは、コンパイル後のDOM操作が行われ、イベントハンドラーが構成され、ウォッチなども構成されます。ディレクティブの宣言では、4つの関数が次のように定義されています。
.directive('directiveName',function () { return { controller: function() { // controller code here... }, compile: { // compile code here... return { pre: function() { // pre-link code here... }, post: function() { // post-link code here... } }; } } })
通常、すべての機能が必要なわけではありません。ほとんどの場合、開発者は単に作成します コントローラ そして ポストリンク 以下のパターンに従って機能します。
.directive('directiveName',function () { return { controller: function() { // controller code here... }, link: function() { // post-link code here... } } })
この構成では、 リンク を参照 ポストリンク 関数。
すべての関数または一部の関数が定義されているかどうかに関係なく、それらの実行順序、特にAngularJSアプリケーションの残りの部分と比較した実行は重要です。
ディレクティブを含む次のHTMLスニペットを検討してください parentDir 、 childDir そして grandChildDir HTMLフラグメントに適用されます。
element.html(element.html());
ディレクティブ内の関数の実行順序は、他のディレクティブと比較して次のとおりです。
コンパイルフェーズが最初に発生します。基本的に、コンパイルフェーズでは、イベントリスナーがDOM要素にアタッチされます。たとえば、特定のDOM要素がにバインドされている場合 $ scope プロパティ、の値で更新できるようにするイベントリスナー $ scope プロパティはDOM要素に適用されます。コンパイルのプロセスは、AngularJSアプリケーションがブートストラップされたルートDOM要素から始まり、深さ優先トラバーサルを使用してDOMのブランチをトラバースし、最初に親をコンパイルし、次にその子をリーフノードまでコンパイルします。
コンパイルが完了すると、ディレクティブをDOMに追加したり、DOMから削除したりすることはできなくなります(ただし、を直接使用することでこれを回避する方法はあります) コンパイルサービス 。次のフェーズは、すべてのディレクティブのコントローラーとプリリンク関数の呼び出しです。コントローラが呼び出されると、 $ scope 利用可能であり、使用することができます。ザ・ $ element コントローラに挿入されたものには、コンパイルされたテンプレートが含まれますが、トランスクルージョンされた子コンテンツは含まれません(トランスクルージョンされたコンテンツは、ディレクティブが適用される開始HTMLタグと終了HTMLタグの間のコンテンツです)。定義上、MVCパターンのコントローラーは、モデルをビューに渡し、イベントを処理するための関数を定義するだけです。したがって、ディレクティブのコントローラーは、コントローラーの目的に違反していることと、トランスクルージョンされた子コンテンツがDOMに追加されていないことの2つの理由で、ディレクティブのDOMを変更しないでください。では、コントローラーは変更以外に何をしますか $ scope ?コントローラを使用すると、子ディレクティブが親ディレクティブと通信できます。コントローラ関数自体は、子ディレクティブが要求した場合に子ディレクティブのリンク後関数に渡されるコントローラオブジェクトと見なす必要があります。したがって、コントローラーは通常、兄弟ディレクティブと子ディレクティブで使用できるプロパティとメソッドを持つオブジェクトを作成することにより、ディレクティブ通信を容易にするために使用されます。親ディレクティブは、子ディレクティブがそのコントローラーを必要とするかどうかを判断できないため、このメソッドのコードを、子ディレクティブで安全に使用できる関数とプロパティに制限することをお勧めします。
コントローラ機能の後、プリリンク機能が実行されます。プレリンク機能は多くの人にとって不思議です。インターネットや本で多くのドキュメントを読んだ場合、この機能はまれな状況でのみ使用され、人々がそれを必要とすることはほとんどないだろうと人々は書いています。それらの同じ説明は、それが使用される可能性がある状況の例を与えることができません。
プレリンク機能は実際にはまったく複雑ではありません。まず、AngularJSのソースコードを確認すると、リンク前関数の優れた例であるディレクティブが見つかります。 熱の それを使用します。どうして?これは、以下を含むプライベートコードを実行するための優れた方法です。 $ scope ;兄弟および子ディレクティブでは呼び出せないコード。コントローラ関数とは異なり、プリリンク関数はディレクティブに渡されません。したがって、を変更するコードを実行するために使用できます。 $ scope その指令の。ディレクティブ 熱の まさにこれを行います。のプリリンク機能が 熱の 実行すると、ディレクティブに渡されたJavaScriptがディレクティブに対して実行されるだけです。 $ scope 。実行の結果は、 $ scope のコントローラー、リンク前およびリンク後の関数の実行中の子ディレクティブへのプロトタイプの継承。ただし、親のリンク前関数のコードを再実行するための子ディレクティブへのアクセスは許可されません。また、ディレクティブは、に関連しない他のコードを実行する必要がある場合があります。 $ scope プライベートにしておきたいこと。
製品を設計するときにクライアントに尋ねる質問
いくつか 経験豊富なAngularJS開発者 これを言うだろう 民間 コードは引き続きコントローラーに配置され、子ディレクティブによって呼び出されない可能性があります。ディレクティブがそれをコーディングした元の開発者によってのみ使用される場合、その引数は当てはまりますが、ディレクティブが他の開発者によって配布および再利用される場合、プリリンク関数にプライベートコードをカプセル化することは非常に有益です。開発者は、ディレクティブが時間の経過とともにどのように再利用されるかを決して知らないため、子ディレクティブによってプライベートコードが実行されないように保護することは、ディレクティブコードをカプセル化するための優れたアプローチです。コントローラ関数にディレクティブ通信のパブリックコードを配置し、プリリンク関数にプライベートコードを配置することをお勧めします。コントローラーと同様に、子ディレクティブのコンテンツはまだリンクされていないため、事前リンクはDOM操作を実行したりトランスクルージョン関数を実行したりしないでください。
ディレクティブごとに、そのコントローラーとプレリンク関数は、その子ディレクティブのコントローラーとプレリンク関数の前に実行されます。すべてのディレクティブのコントローラーとプレリンクフェーズが完了すると、AngularJSはリンクフェーズを開始し、各ディレクティブのポストリンク機能を実行します。リンクフェーズは、コンパイル、コントローラー、およびリンク前の実行フローとは逆に実行され、リーフDOMノードから開始して、ルートDOMノードまで進みます。リンク後のDOMトラバーサルは、ほとんどが深さ優先のパスに従います。各子ディレクティブがリンクされると、そのポストリンク機能が実行されます。
ポストリンク関数は、カスタムAngularJSディレクティブで最も一般的に実装される関数です。この関数では、合理的なほとんどすべてを実行できます。 DOMは操作できます(それ自体と子要素のみ)。 $ scope が使用可能である場合、親ディレクティブのコントローラーオブジェクトを使用したり、トランスクルージョン関数を実行したりできます。ただし、いくつかの制限があります。新しいディレクティブはコンパイルされないため、DOMに追加できません。さらに、すべてのDOM操作はDOM関数を使用して実行する必要があります。単に呼び出す html DOM要素の関数と新しいHTMLを渡すと、コンパイルプロセス中に追加されたすべてのイベントハンドラーが削除されます。たとえば、これらは期待どおりに機能しません。
element.html(element.html() + ' new content ');
または
|_+_|
コードによってHTMLが変更されることはありませんが、DOM要素の文字列バージョンを再割り当てすると、コンパイルプロセス中に作成されたすべてのイベントハンドラーが削除されます。通常、ポストリンク関数はイベントハンドラーを接続するために使用されます。 $ watch と $ observe s。
リンク後の機能がすべて実行されると、 $ scope コンパイルおよびリンクされたDOM構造に適用され、AngularJSページが有効になります。
これは、各関数の目的、実行時に使用できるもの、および各関数を適切に使用するためのベストプラクティスを一覧にしたグラフです。