web-dev-qa-db-ja.com

ディレクティブを定義するときの 'controller'、 'link'、および 'compile'関数の違い

ディレクティブロジックにコントローラ関数を使用しているような場所もあれば、リンクを使用している場所もあります。 Angularホームページのタブの例では、一方にはcontrollerを使用し、もう一方にはlinkを使用しています。両者の違いは何ですか?

390
user1558259

私はあなたの質問を少し拡張し、コンパイル機能も含めます。

  • コンパイル関数 - テンプレートDOM操作(すなわち、tElement = template要素の操作)に使用します。したがって、のすべてのDOMクローンに適用される操作です。ディレクティブに関連したテンプレート(リンク関数(または前後のリンク関数)も必要で、コンパイル関数を定義した場合、'link'属性が定義されていると'compile'属性は無視されるため、コンパイル関数はリンク関数を返す必要があります。)

  • リンク関数 - 通常はリスナコールバック(スコープ上の$watch式)の登録とDOMの更新(すなわちiElementの操作=個々のインスタンス要素)に使用します。テンプレートが複製された後に実行されます。たとえば、<li ng-repeat...>内では、その特定の<li>要素に対して<li>テンプレート(tElement)が(iElementに)複製された後にlink関数が実行されます。 $watchを使用すると、ディレクティブにスコーププロパティの変更を通知できます(スコープは各インスタンスに関連付けられます)。これにより、ディレクティブは更新されたインスタンス値をDOMにレンダリングできます。

  • コントローラー関数 - 他のディレクティブがこのディレクティブと対話する必要があるときに使用しなければなりません。例えば、AngularJSホームページでは、paneディレクティブは自身をtabsディレクティブで管理されているスコープに追加する必要があります。したがって、tabsディレクティブは、paneディレクティブがアクセスまたは呼び出すことができるコントローラメソッド(think API)を定義する必要があります。

    tabsおよびpaneディレクティブのより詳細な説明、ならびにtabsディレクティブが($scopeではなく)thisを使用してコントローラ上に関数を作成する理由については、 を参照してください。 AngularJSコントローラの 'this'と$のスコープ

一般的に、メソッド、$watchesなどは、ディレクティブのコントローラーまたはリンク関数のいずれかに入れることができます。コントローラが最初に実行されますが、これが重要になることがあります(ctrl関数とlink関数が2つのネストされた指令で実行されるとログに記録される フィドル を参照)。 Joshが コメント で述べたように、フレームワークの他の部分との一貫性を保つために、スコープ操作関数をコントローラ内に配置することをお勧めします。

630
Mark Rajcok

Markの答えを補完するものとして、コンパイル機能はスコープへのアクセスを持っていませんが、リンク機能は持っています。

私はこのビデオを本当にお勧めします。 Misko Hevery(AngularJSの父親)によるDirectives の作成。相違点といくつかのテクニックについて説明しています。 (コンパイル機能とリンク機能の違いはビデオの 14:41マーク )。

56
Pixic
  1. コンパイル前にコードを実行する:コントローラーを使用する
  2. コンパイル後のコードの実行:useLink

一般的な慣習:ビジネスロジックをコントローラに記述し、DOM操作をリンクに記述します。

これとは別に、他のディレクティブのリンク関数から1つのコントローラ関数を呼び出すことができます。たとえば、3つのカスタムディレクティブがあります。

<animal>
<panther>
<leopard></leopard>
</panther> 
</animal>

そして、あなたは "leopard"ディレクティブの内側から動物にアクセスしたいのです。

http://egghead.io/lessons/angularjs-directive-communication はディレクティブ間通信について知るのに役立ちます

35
Rahul

コンパイル関数 -

  1. コントローラとリンク関数の前に呼び出されます。
  2. コンパイル関数にはオリジナルのテンプレートDOMがあるので、AngularJSがインスタンスの作成前とスコープの作成前にオリジナルのDOMを変更できます。
  3. ng-repeatは完璧な例です - 元の構文はテンプレート要素、HTMLの繰り返し要素はインスタンスです。
  4. 複数の要素インスタンスと1つのテンプレート要素のみが存在できます
  5. 範囲はまだ利用できません
  6. コンパイル関数は関数とオブジェクトを返すことができます
  7. (リンク後)関数を返す - コンパイル関数が空のときに、configオブジェクトのlinkプロパティを介してリンク関数を登録するのと同じです。
  8. preおよびpostプロパティを介して登録された関数を持つオブジェクトを返す - リンク段階でリンク関数をいつ呼び出すべきかを制御できます。下記のプレリンクおよびポストリンク機能に関する情報を参照してください。

構文

function compile(tElement, tAttrs, transclude) { ... }

コントローラー

  1. コンパイル関数の後に呼び出されます
  2. スコープはこちら
  3. 他のディレクティブからアクセスできます(require属性を参照)

プレリンク

  1. リンク機能は、DOMリスナーの登録とDOMの更新を担当します。テンプレートが複製された後に実行されます。これがディレクティブロジックの大部分が置かれる場所です。

  2. あなたはangular.elementを使ってコントローラのDOMを更新することができますが、要素はlink関数で提供されているのでこれは推奨されません

  3. リンク前機能は、angle jsがすでに子要素をコンパイルしたが、子要素のpostリンクが呼び出される前に実行されるロジックを実装するために使用されます。

ポストリンク

  1. リンク機能のみを持つディレクティブ、angleは機能をポストリンクとして扱う

  2. postはコンパイル、コントローラ、プリリンク機能の後に実行されるので、これがディレクティブロジックを追加するための最も安全でデフォルトの場所と見なされる理由です。

6
Sunil Garg