209

誰か簡単な言葉で説明できますか?

ドキュメントは少し鈍いようです。どちらをいつ使用するかの本質と全体像がわかりません。この 2 つを対比する例は素晴らしいでしょう。

4

7 に答える 7

217
  • compile 関数 -テンプレートDOM 操作 (つまり、tElement = テンプレート要素の操作) に使用します。したがって、ディレクティブに関連付けられたテンプレートのすべての DOM クローンに適用される操作です。

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

DOM 変換は、コンパイル関数および/またはリンク関数で実行できることに注意してください。

ほとんどのディレクティブは特定の DOM 要素インスタンス (およびそのインスタンス スコープ) のみを処理するため、ほとんどのディレクティブはリンク関数のみを必要とします。

scopeどちらを使用するかを決定するのに役立つ 1 つの方法: コンパイル関数が引数を受け取らないことを考慮して ください。(トランスクルードされたスコープを受け取るトランスクルード リンク関数の引数を意図的に無視しています。これはめったに使用されません。) したがって、コンパイル関数は、(インスタンス) スコープを必要とする、やりたいことは何もできません。モデル/インスタンス スコープ プロパティを $watch しない、インスタンス スコープ情報を使用して DOM を操作できない、インスタンス スコープで定義された関数を呼び出せない、など。

ただし、コンパイル機能 (リンク機能など) は属性にアクセスできます。したがって、DOM 操作にインスタンス スコープが必要ない場合は、コンパイル関数を使用できます。これらの理由から、コンパイル関数のみを使用するディレクティブの例を次に示します。属性を調べますが、ジョブを実行するためにインスタンス スコープは必要ありません。

コンパイル関数のみを使用するディレクティブの例を次に示します。ディレクティブはテンプレート DOM を変換するだけでよいため、コンパイル関数を使用できます。

どちらを使用するかを決定する別の方法: リンク関数で「要素」パラメーターを使用しない場合、おそらくリンク関数は必要ありません。

ほとんどのディレクティブにはリンク機能があるため、例を提供するつもりはありません。非常に簡単に見つけることができるはずです。

コンパイル関数とリンク関数 (またはリンク前関数とリンク後関数) が必要な場合、コンパイル関数はリンク関数を返さなければならないことに注意してください。これは、「コンパイル」属性が定義されている場合、「リンク」属性が無視されるためです。

こちらもご覧ください

于 2013-01-13T03:24:58.803 に答える
50

ドキュメントから:

コンパイラ

コンパイラは、属性を探してDOMをトラバースするAngularサービスです。コンパイルプロセスは2つのフェーズで行われます。

  1. コンパイル: DOMをトラバースし、すべてのディレクティブを収集します。結果はリンク関数です。

  2. リンク:ディレクティブをスコープと組み合わせて、ライブビューを生成します。スコープモデルでの変更はすべてビューに反映され、ビューに対するユーザーの操作はすべてスコープモデルに反映されます。スコープモデルを信頼できる唯一の情報源にする。

このような一部のディレクティブng-repeatは、コレクション内のアイテムごとにDOM要素を1回複製します。クローンテンプレートをコンパイルする必要があるのは1回だけで、クローンインスタンスごとに1回リンクするだけでよいため、コンパイルとリンクのフェーズがあるとパフォーマンスが向上します。

したがって、少なくとも場合によっては、最適化として2つのフェーズが別々に存在します。


@UmurKontacıから

DOM変換を行う場合は、である必要がありますcompile。動作の変更であるいくつかの機能を追加する場合は、に含める必要がありlinkます。

于 2012-08-28T17:08:23.830 に答える
18

これは、ディレクティブに関する Misko の講演からのものです。http://youtu.be/WqmeI5fZcho?t=16m23s

コンパイラ機能は、テンプレートで機能するものと、たとえばクラスをテンプレートに追加するなどしてテンプレート自体を変更できるものと考えてください。ただし、リンク関数はスコープにアクセスでき、特定のテンプレートのインスタンス化ごとに 1 回実行されるリンク関数であるため、実際に 2 つをバインドする作業を行うのはリンク関数です。したがって、コンパイル関数内に配置できる唯一の種類のものは、すべてのインスタンスに共通のものです。

于 2013-01-16T13:33:16.153 に答える
10

スレッドに少し遅れました。しかし、将来の読者のために:

Angular JS でのコンパイルとリンクを非常に優れた方法で説明している次のビデオに出くわしました。

https://www.youtube.com/watch?v=bjFqSyddCeA

ここにすべての内容をコピー/入力するのは好ましくありません。ビデオからいくつかのスクリーンショットを撮りました。これは、コンパイル フェーズとリンク フェーズのすべての段階を説明しています。

Angular JS でのコンパイルとリンク

Angular JS でのコンパイルとリンク - ネストされたディレクティブ

2 番目のスクリーンショットは少し紛らわしいです。しかし、ステップの番号付けに従うと、非常に簡単です。

最初のサイクル: 最初にすべてのディレクティブに対して「コンパイル」が実行されます。
2 サイクル目: 「Controller」と「Pre-Link」が実行されます (1 つずつ) 3 サイクル目: 「Post-Link」が逆の順序で実行されます (最も内側から開始)

以下は、上記を示すコードです。

var app = angular.module('app', []);

app.controller('msg', ['$scope', function($scope){

}]);

app.directive('メッセージ', function($interpolate){
    戻る{

        コンパイル:関数(tElement、tAttributes){
            console.log(tAttributes.text + " -コンパイル中..");
            戻る {

                前: 関数 (スコープ、iElement、iAttributes、コントローラー){
                    console.log(iAttributes.text + " -In pre..");
                }、

                投稿: 関数 (スコープ、iElement、iAttributes、コントローラー){
                    console.log(iAttributes.text + " -In Post..");
                }

            }
        }、

        コントローラ: 関数($scope, $element, $attrs){
            console.log($attrs.text + " - コントローラー内..");
        }、

    }
});
<body ng-app="app">
<div ng-controller="msg">
    <div message text="first">
        <div message text="..second">
            <div message text="....third">

            </div>              
        </div>  
    </div>
</div>

アップデート:

同じビデオのパート 2 はこちらから入手できます: https://www.youtube.com/watch?v=1M3LZ1cu7rw このビデオでは、Angular JS のコンパイルおよびリンク プロセス中に DOM を変更し、イベントを処理する方法について、簡単な例で詳しく説明しています。 .

于 2016-09-27T14:10:08.837 に答える
6

2 つのフェーズ: コンパイルとリンク

コンパイル:

ディレクティブ (要素 / 属性 / クラス / コメント) を探して DOM ツリーをトラバースします。ディレクティブをコンパイルするたびに、そのテンプレートが変更されるか、まだコンパイルされていない内容が変更される場合があります。ディレクティブが一致すると、リンク関数が返されます。この関数は、後のフェーズで要素をリンクするために使用されます。コンパイル フェーズの最後には、コンパイルされたディレクティブとそれに対応するリンク関数のリストが表示されます。

リンク:

要素がリンクされると、DOM ツリーは DOM ツリーの分岐点で壊れ、内容はテンプレートのコンパイル済み (およびリンク済み) のインスタンスに置き換えられます。元の置き換えられたコンテンツは破棄されるか、トランスクルージョンの場合はテンプレートに再リンクされます。トランスクルージョンでは、2 つのピースが再びリンクされます (テンプレート ピースが中央にあるチェーンのようなものです)。リンク関数が呼び出されると、テンプレートは既にスコープにバインドされており、要素の子として追加されています。リンク機能は、DOM をさらに操作し、変更リスナーをセットアップする機会です。

于 2014-05-29T08:27:38.747 に答える
3

この質問は古いので、役立つ短い要約を作成したいと思います。

  • すべてのディレクティブ インスタンスに対して 1 回呼び出されるコンパイル
  • コンパイルの主な目的は、リンク (および場合によってはプリ/ポスト) 関数/オブジェクトを返す/作成することです。ディレクティブのインスタンス間で共有されるものを初期化することもできます。
  • 私の意見では、「リンク」はこの機能の紛らわしい名前です。私は「事前レンダリング」を好むでしょう。
  • link はディレクティブ インスタンスごとに呼び出され、その目的は DOM でのディレクティブのレンダリングを準備することです。
于 2016-11-19T11:14:42.373 に答える