指令は、HTMLにいくつかの新しいトリックをプレイするように教える方法です。 DOMコンピレーション中、ディレクティブはHTMLと実行されます。これにより、指令登録動作またはDOM構造の変換が可能になります。
Angularには、組み込みのディレクティブのセットが付属しています。これは、Webアプリの構築に非常に役立ちます。拡張を続けると、HTMLでドメイン固有言語(DSL)を定義できます。
1。HTMLの引用指令
指令には、NgbindなどのCamel Cased Styleの命名があります(プロパティでは使用できないようです〜)。ただし、ディレクティブは、次のように接続する必要があるスネークボトムタイプ(ヘビのケース)で名前を付けることもできます。オプションのオプションとして、ディレクティブには、HTML検証のニーズを満たすために「x-」または「data-」をプレフィックスすることができます。これが指令の法的名です。
指令は、要素名、属性、クラス、およびコメントに配置できます。以下は、指令であるMyDirを引用する同等の方法です。 (しかし、多くの指令は「プロパティ」の使用に限定されています)
<span my-dir = "exp"> </span> <span> </span> <my-dir> </my-dir> <! - ディレクティブ:my-dir exp->
指令はさまざまな方法で引用でき、次のリストはn同等の方法を示します。
<!doctype html> <html lang = "zh-cn" ng-app> <head> <meta charset = "utf-8"> <title> invoke-directive </title> <style type = "text/css"> .ng-cloak {display:none:none; } </style> </head> <body> <div ng-controller = "myctrl"> hello <input ng-model = "name"/> <hr/> ngbind = "name"これは使用できません~~ <span ngbind = "name"> </span> <br/> ng:bind = "bind" <span ng: "> < ng_bind = "name" <span ng_bind = "name"> </span> <br/> ng-bind = "name" <span ng-bind = "name"> </span> <br/> data-ng-bind = "name" <span data-ng-bind = "name"> </span> <br/> x-bind = "ng- span x-ng-bind = "name"> </span> <br/> </div> <script src = "../ angular-1.0.1.js" type = "text/javascript"> </script> <script> <script> <script> <"text/javascript"> function myctrl($ scope){$ scope.name = "Beauty〜"; } </script> </body> </html>2。文字列補間
コンピレーションプロセス中、コンパイラは$補間サービスを通じて属性({{{Something}}}など)に埋め込まれた式とテキストを一致させます。これらの式は時計として登録され、ダイジェストサイクルの一部として一緒に更新されます(以前はダイジェストループではありませんでしたか?!)。ここに簡単な補間があります:
<img src = "img/{{username}}。jpg"/> hello {{username}}!
3。コンピレーションプロセス、および指令マッチング
HTMLを「コンパイル」するための3つのステップ:
1.最初に、ブラウザの標準APIを介してHTMLをDOMオブジェクトに変換します。これは非常に重要なステップです。テンプレートは解析可能でなければならないため(仕様に準拠しています)。これは、一般にDOM要素ではなく文字列に基づいているほとんどのテンプレートシステムと比較できます。
2。domのコンパイルは、$ comple()メソッドを呼び出すことによって行われます。このメソッドはDOMを横断し、指令に一致します。試合が成功した場合、対応するDOMと一緒にディレクティブリストに追加されます。指定されたDOMに関連付けられているすべてのディレクティブが識別される限り、それらは優先順位でソートされ、その順序でコンパイル()関数を実行します。ディレクティブコンパイル関数には、DOM構造を変更する機会があり、リンク()関数の解析を生成する責任があります。 $ compile()メソッドは、ディレクティブ自体のコンパイル関数によって返されるリンク関数のコレクションである結合リンク関数を返します。
3.前のステップで返されたリンク関数を介して、テンプレートをスコープに接続します。これにより、ディレクティブ自身のリンク関数を呼び出し、要素にリスナーを登録し、スコープでいくつかの時計を作成できます。これは、範囲とDOMの間の双方向の瞬時の結合です。スコープが変更されると、DOMは対応する応答を取得します。
var $ compile = ...; //コードに注入されたvar scope = ...; var html = '<div ng-bind =' exp '> </div>'; //ステップ1:htmlをdom element var template = angular.element(html)に解析する; //ステップ2:テンプレートのコンパイルvar linkfn = $ compile(テンプレート); //ステップ3:コンパイルされたテンプレートをスコープにリンクします。 linkfn(scope);
4。コンパイル/リンク分離の背後にある理由
この時点で、コンパイルプロセスがコンパイルとリンクの2つのステップに分割される理由を疑問に思うかもしれません。これを理解するために、本当の例(リピーター)を見てみましょう
hello {{user}}、これらのアクションがあります:<ul> <li ng-repeat = "user.actions"> {{action.description}} </li> </ul>簡単に言えば、コンパイルとリンクの2つのステップを分離する理由は、リピーターなど、モデルが変更された後に対応するDOM構造を変更する必要がある場合があるためです。
上記の例がコンパイルされると、コンパイラはすべてのノードを繰り返して指令を見つけます。 {{user}}は、補間指令の例です。 ngrepeatは別の指令です。しかし、ngrepeatには困難があります。ユーザーのアクションごとに新しいLIをすばやく作成する機能が必要です。これは、LIのクローニングと特定のアクションを埋め込む目的を満たすために(ここではユーザーのアクションの値の1つを指します)、LI要素のクリーンなコピーを保持する必要があります。しかし、Li要素をクローニングするだけでは十分ではありません。また、LIは、その指令({{action.descriptions}})を正しい範囲で解析できるようにコンパイルする必要があります。元の方法は通常、Li要素のコピーを挿入してからコンパイルします。ただし、コンパイルプロセスではDOMノードツリーを通過し、ディレクティブを見つけて実行する必要があるため、各LI要素のコピーをコンパイルすると遅くなります。リピーターを介して100個のアイテムを処理する必要があるコンパイルがある場合は、パフォーマンスの問題に固執します。
問題の解決策は、コンピレーションプロセスを2つのステップに分解することです。コンパイルステージはすべてのディレクティブを認識し、優先順位でソートし、リンク段階で特定の範囲を特定のLIで結合します。
Ngrepeatは、個々のLIを個別にコンパイルして、コンパイルプロセスがLI要素に陥るのを防ぎます。 LI要素のコンパイル結果は、LI要素に含まれるすべてのディレクティブを含むディレクティブリンク関数であり、特定のLI要素のコピーに接続する準備ができています。実行時に、Ngrepeatは式を監視し、Li要素のコピーの配列にアイテムとして追加され、クローン化されたLI要素の新しいスコープを作成し、コピーに対応するリンク関数を呼び出します。
要約:
1.コンパイル関数 - コンパイル関数は、DOM要素のテンプレート(DOM自体とその内部構造)のテンプレートを変更するのではなく、指定されたDOM要素を操作することにのみ関与することにのみ関与するため、ディレクティブではコンパイル関数が比較的まれです。パフォーマンスを最適化するために、ディレクティブインスタンスで共有できる一部の操作をコンパイル関数に移動できます。
2。リンク関数 - リンク関数がないディレクティブはほとんどありません。リンク関数を使用すると、ディレクティブがDOM Elementインスタンスの指定されたコピーにリスナーを登録するか、特定のコンテンツをスコープからDOMにコピーできます。
5。指令を書く(簡単なバージョン)
この例では、入力形式に従って現在の時刻を表示するディレクティブを作成します。
<!doctype html> <html lang = "zh-cn" ng-app = "timeformat"> <head> <head> <meta charset = "utf-8"> <title> time-format </titleformat </head> <body> <div ng-controller = "myctrl" id = ""/<""/<"" "/> <" "/> <hr = < <! - 次のことで、属性x-current-timeを使用して上記の法的命名を試してみてください~~ current:time、current-time、current_time、data-current-time -_- !!! - >現在の時間は:<span x-current-time = "format" id = "myformat"> </span> <br/> <button ng-click = "remove()"> span </button> </div> <script src = "../ angular-1.0.1.js" type = "text/javascript"> </script> <スクリプト> < type="text/javascript">angular.module("TimeFormat", []) //Register the directive factory method of "currentTime" in the TimeFormat application//As mentioned above, dependency injection can be written directly in the function parameters, injected here $timeout and dataFilter .directive("currentTime", function (dateFilter) { //This is the linking function mentioned above. (There is no need to add aコンパイル、なぜ?)関数(scope、element、attr){var intervalid; scope。 })。コントローラー( "myctrl"、function($ scope、$ rotscope){$ scope.format = "m/d/yy h:mm:ss a"; $ scope.remove = function(){var oformat = document.getElementbyid( "myformat"); $ Destowedは、長い間試しました!6。指令を書く(詳細バージョン)
以下は、ディレクティブ(ディレクティブオブジェクト定義テンプレート)のサンプル作成です。詳細なリストをご覧になりたい場合は、読み続けてください。
var mymodule = angular.module(...); mymodule.directive( 'directivename'、function Factory(injectables){var directivedefinitionObject = {priority:0、template: '<div> </div>'、directive.html '、置換:false、transclude:fals、balse:' a '、scope:fals、compile(compile(compile)、compile(false、transclude) Pre:function prelink(scope、iElment、controller){...}、post:function postlink(scope、iettrs、controller){...}}、リンク:function postlink(scope、iEtrement、iattrs){...}};ほとんどのシナリオでは、正確な制御は必要ないため、上記の定義を簡素化できます。テンプレートの各部分を定義することについては、次の章で説明します。この章では、テンプレートを定義するこのスケルトンの異性体のみに焦点を当てています(このスケルトンの異性体、私は理解していません...みんなの追加を楽しみにしています)。
コードを簡素化する最初のステップは、デフォルト値に依存することです。したがって、上記のコードは次のことを簡素化できます。
var mymodule = angular.module(...); mymodule.directive( 'directivename'、function Factory(injectables){var directivedefinitionObject = {compile:function compile(telement、tattrs){return function postlink(scope、iElement、iattrs){...}}}; return directivedefinitionObject;});ほとんどのディレクティブは、テンプレート変換ではなくインスタンスのみを気にかけているため、さらに単純化することができます(翻訳されています...みんなの追加を楽しみにしています):
var mymodule = angular.module(...); mymodule.directive( 'directivename'、function Factory(injectables){return function postlink(scope、iElement、iattrs){...}});7。工場の方法
工場の方法は、指示を作成する責任があります。コンパイラが最初にディレクティブと一致するときだけ、一度だけ使用されます。ここで初期化操作を行うことができます。工場の方法は$ injector.invokeを介して実行され、すべての注入宣言ルール(注入注釈の規則)に準拠することができ、注射可能になります。
8。ディレクティブ定義オブジェクト説明
ディレクティブ定義オブジェクトは、コンパイラ構造を提供します。プロパティは次のとおりです。
1.Name-現在のスコープの名前。デフォルト値は、登録するときに使用できます(記入されていません)。
2.優先順位 - 同じDOM要素で複数のディレクティブが定義されている場合、実行命令を明確にする必要がある場合があります。このプロパティは、ディレクティブコンパイル関数呼び出しの前にソートするために使用されます。優先順位が同じ場合、実行命令が不確かです(予備実験の後、優先度が高い人が最初に実行され、同じレベルが「拘束後の」実行に似ています。さらに、テスト中に少し不注意でした。
3.ターミナル(最後のグループ) - 「true」に設定されている場合、現在の優先度が実行の最後のグループの指令になることを意味します。指令が現在の優先事項と同じである場合、それらはまだ実行されますが、順序は不確かです(順序は不確かですが、基本的に優先順位と同じです。現在の優先度が実行された後、より低い優先度は再び実行されません)。
4.スコープ - に設定されている場合:
1).true-この指令のために新しいスコープが作成されます。新しいスコープを必要とするのと同じ要素に複数のディレクティブがある場合、1つのスコープのみを作成します。新しいスコープルールはルートテンプレートには適用されないため、ルートテンプレートは新しいスコープを取得する傾向があります。
2)。{}(オブジェクトハッシュ) - 新しい分離型スコープが作成されます。 「分離」範囲と一般的な範囲の違いは、プロトタイプを通じて親の範囲から継承されないことです。これは、再利用可能なコンポーネントの作成に非常に役立ち、親の範囲からデータの読み取りまたは変更を効果的に防止できます。この独立したスコープは、親スコープから派生した一連のローカルスコーププロパティを備えたオブジェクトハッシュを作成します。これらのローカルプロパティは、テンプレート-_-!の値をエイリアスするのに役立ちます。地元の定義は、そのソース#&&@#)($&@#_)へのローカルスコーププロパティのハッシュです。
3)。 @または@attr- DOMプロパティにローカルスコーププロパティを作成します。プロパティ値は常に文字列タイプであるため、この値は常に文字列を返します。属性名が@ATTRを介して指定されていない場合、ローカル名は常にDOM属性の名前とともにあります。たとえば、<widget my-attr =” hello {{name}} ">、ウィジェットの範囲は次のように定義されます。{localname: '@myattr'}。次に、ウィジェットスコーププロパティのローカル名は、「hello {{name}}」で変換された実際の値をマップします。名前属性値が変更された後、ウィジェットスコープのローカル名属性もそれに応じて変更されます(片道のみ、以下の「=」とは異なります)。名前属性は親の範囲で読み取られます(コンポーネントスコープではありません)
4)。= OR =式(ここではタート) - ローカルスコープ属性と親スコープ属性の間に双方向の結合を設定します。 attr名が指定されていない場合、ローカル名は属性名と一致します。たとえば、<ウィジェットmy-attr =” parentModel”>、ウィジェットで定義されたスコープは次のとおりです。 ParentModelで変更が発生した場合、LocalModelも変更され、逆も同様です。 (双方向のバインディング)
5)。&またはattr-親スコープのコンテキストで式を実行する方法を提供します。 attr名が指定されていない場合、ローカル名は属性名と一致します。たとえば、<ウィジェットmy-attr =” count = count + value”>、ウィジェットの範囲は次のように定義されます。一般的に言えば、隔離範囲から式を介して親の範囲にデータを渡したいと考えています。これは、ローカル変数のキー値のマップを式のラッパー関数に渡すことで実行できます。たとえば、式が増分(量)の場合、localfn({amont:22})を介してlocalfnを呼び出して量の値を指定できます(上記の例は実際にはわかりません。どこに行きましたか?)。
5.Controller-コントローラーコンストラクター。コントローラーは、リンク前のステップの前に初期化し、指定された名前と必要なディレクティブを介して共有できるようにします(以下の要求プロパティを参照)。これにより、指令が相互に通信し、相互の行動を強化することができます。コントローラーは、デフォルトで次のローカルオブジェクトを注入します。
1)。$スコープ - 現在の要素と組み合わせたスコープ
2)。$要素 - 現在の要素
3)。$ attrs-現在の要素の属性オブジェクト
4)。$ transclude-現在のトランスポーズスコープ:function(cloneLinkingfn)にプリバウンドするトランスポーズリンク関数。 (正しい翻訳範囲に事前に結合するトランスクルーデリンク関数)
6. Require-別のコントローラーに、それを現在のディレクティブリンク関数に渡すように要求します。直接コントローラーの名前が渡される必要があります。この名前に対応するコントローラーが見つからない場合、エラーがスローされます。名前には、次のように前に付くことができます。
1)。 - 例外をスローしないでください。これにより、この依存関係はオプションになります。
2)。^ - 親要素を検索できるコントローラー
7. Restrict-指定された宣言法に指示を制限するEACMのサブセットの文字列。省略された場合、指令は属性を介した宣言のみを許可します。
1)E-要素名:<my-directive> </my-directive>
2).a-属性名:<div my -directive =” exp”> </div>
3)。 c-クラス名:<div class = "my -directive:exp;"> </div>
4).M-コメント:<! - 指令:my-directive exp->
8.Template-交換がtrueの場合、テンプレートコンテンツを現在のHTML要素に置き換え、元の要素の属性とクラスを移行します。 falseの場合、テンプレート要素は現在の要素の子要素として扱われます。詳細については、「Widgetsの作成」の章をご覧ください(ここで...作成コンポーネントの作成が利用可能です...)
9.templateurl-は基本的にテンプレートと同じですが、テンプレートは指定されたURLを介してロードされます。テンプレートの読み込みは非同期であるため、コンパイルとリンクは一時停止され、ロード後に実行されます。
10. replace -trueに設定されている場合、テンプレートは、子要素として現在の要素に追加される代わりに、現在の要素を置き換えます。 (注:trueの場合、テンプレートにはルートノードが必要です)
11. Transclude-要素のコンテンツをコンパイルして、指令で使用できるようにします。 (テンプレート内)使用する必要があります(参照)。輸血の利点は、リンク関数が現在の範囲に事前に縛られる翻訳関数を取得できることです。一般的に、ウィジェットを作成し、分離スコープを作成します。翻訳は子供ではなく、分離株の兄弟です。これにより、ウィジェットに私的状態があり、輸血は親(プレイソレート)範囲に結合されます。 (私は上記の段落を理解していません。しかし、実際の実験では、myDirectiveが<any-directive> {{name}} </my-directive> </any-direction>を介して呼び出され、トランスクルーデがtrueに設定されています。他のものが包まれている場合は、shutagの余分なスパンになります。
1).true-この指令のコンテンツを変換します。 (この意味で、コンテンツを直接コンパイルし、指定された場所に移動することです)
2)。「要素」 - 優先度が低い他の指令を含む要素全体を変換します。 (たとえば、コンテンツ全体をコンパイルした後、それは全体として扱われ(外側に包まれた)、指定された場所に挿入されます)
12.comPile-これがコンパイル関数です。これについては、次の章で詳しく説明します。
13.link-以下はリンク関数です。これについては、次の章で詳しく説明します。このプロパティは、コンパイルプロパティが定義されていない場合にのみ使用されます。
9.コンパイル関数
関数コンパイル(Telement、Tattrs、TransClude){…}
コンパイル関数は、DOMテンプレートの変換を処理するために使用されます。ほとんどのディレクティブは変換テンプレートを必要としないため、コンパイルは頻繁に使用されません。コンパイル機能、一般にDOMテンプレート(ngrepeatなど)を変換する必要がある関数、または非同期(ngviewなど)をコンテンツをロードする必要がある指令。コンパイル関数には次のパラメーターがあります。
1.テレメント - テンプレート要素は、現在のディレクティブ要素を使用します。現在の要素または現在の要素の子要素の下でテンプレート変換を行うだけで安全です。
2.Tattrs -Template属性 - 現在の要素で宣言された標準化された属性は、さまざまな指令で共有できます。詳細については、属性の章を参照してください
3.変換のためのリンク関数をトランスクルーディング:関数(スコープ、クローンリンク)。
注:テンプレートがクローン化されている場合、テンプレートインスタンスとリンクインスタンスは同じオブジェクトになることはできません。これを行うには、すべてのクローンに適用されるコンパイル関数のDOM変換以外に何もすることは安全ではありません。特に、DOMイベントリスナーの登録操作は、コンパイル関数ではなく、リンク関数で実行する必要があります。
コンパイル関数には戻り値を持つことができ、タイプは関数またはオブジェクトにすることができます。
1。通常、コンパイル関数が不要になったときに使用されます(空)。これは、リンクを介したリンク関数を登録するのと同等です(テンプレートの属性を直接定義します)。
2。前とポストのプロパティを含むオブジェクトを返します - リンクフェーズ中にリンク関数が呼び出されるときに制御できます。詳細については、リンク前およびリンク後の機能に関する次の章をご覧ください。
10。リンク関数
関数リンク(scope、iElement、iattrs、コントローラー){…}
リンク関数は、DOMイベントリスナーの登録を担当し、DOM更新操作を実行することもできます。リンク関数は、テンプレートクローニング操作が完了した後に実行されます。指令のロジックのほとんどはここに保存されています。
1.SCOPE -SCOPE-時計の登録に使用されます(http://docs.angularjs.org/api/ng.$rootscope.scope#$watch)。
2.ELEMENT-要素インスタンス - 指令で使用される要素。ポストリンク関数の子要素を操作することは安全です。子供の要素がリンクされているからです(モデルに接続されていますか?!)。
3.Iattrs -Attributeインスタンス - 標準電流要素の属性リスト。すべての指令リンク関数間で共有されます。
4.Controller-コントローラーインスタンス - コントローラーの1つが現在の要素の指令で定義されている場合、ここでコントローラーのインスタンスを取得できます。このコントローラーはすべてのディレクティブ間で共有されているため、各指令はコントローラーを通信チャネルとして扱うことができます。
リンク前機能
子どもの要素がリンクされる前に実行します。コンパイラのリンク関数は、リンク時に正しい要素を特定しない場合があるため、ここでDOM変換を行うことは安全ではありません。
リンク後機能
子どもの要素がリンクされた後に実行します。ここでDOM変換を実行しても安全です。
11。属性
属性オブジェクト - link()またはcompile()の引数として - 次のアクセス方法です。
1。標準化された属性名:ngbindなどの指令であるため、「ng:bind」、「x-ng-bind」などの多くの形式で明らかにすることができます。
2。指令間の通信:すべてのディレクティブは、属性オブジェクトインスタンスを共有しているため、ディレクティブは属性オブジェクトを介してディレクティブ間で通信できます。
3。サポート補間:補間属性は属性オブジェクトに割り当てられ、他のディレクティブが補間値を読み取ることができます。
4.補間された属性を観察する:補間を含む属性を介して属性値の変化を観察します(たとえば、src =” {{bar}} ")。それは非常に効果的であるだけでなく、単に実際の価値を取得する唯一の方法でもあります。リンク段階では、補間が割り当てられていないため(実際の値に置き換えられています)、現時点でアクセスすると、結果は未定義です。
<!doctype html> <html lang = "zh-cn" ng-app = "directiveproperty"> <head> <meta charset = "utf-8"> <title> directive-attribute-test </title> <style type = "text/css"> .ng-cloak {display:none; } </style> </head> <body ng-controller = "myctrl"> <入力タイプ= "text" ng-model = "ng-model =" ng-model = "value =" myname "/> <p my-attr =" 123 "directive-p2 attr-dd =" {{name}}} " type = "text/javascript"> </script> <script type = "text/javascript"> var app = angular.module( "directiveProperty"、[]); App.Controller( "myctrl"、function($ scope){$ scope.name = "my little dada";}); var directiveP2 = app.directive( "directivep2"、function(){return {link:console.log( "myattr:" + lattr.myattr); // 123 console.log( "myattr:" + lattr.attrdd); console.log( 'atrddは' +値に変更しました12。輸血と範囲を理解します
多くの場合、再利用可能なコンポーネントが必要です。これは、単純なダイアログコンポーネントがどのように機能するかを示す擬似コードです。
<button ng-click = "show = true"> show </button> <ダイアログ= "show" on-cancel = "show = false" on-ok = "show = false; dosomething()">ボディはここに行きます:{{username}}}}}}}。[表示]ボタンをクリックすると、ダイアログが開きます。ダイアログには、データ「ユーザー名」にバインドされているタイトルがあり、ダイアログ内に配置したい段落もあります。
以下は、ダイアログ用に書かれたテンプレート定義です。
<div ng-show = "show()"> <h3> {{title}} </h3> <div ng-transclude> </div> <div> <button ng-click = "onok()"> save andy </button> <button ng-click = "oncancel()">範囲で特別な治療を行わない限り、これは正しくレンダリングされません。
解決する必要がある最初の問題は、ダイアログテンプレートがタイトルが定義されることを期待し、初期化されたときにユーザー名にバインドされることです。さらに、ボタンには、スコープに表示されるには、OnokとOncancelの2つの機能が必要です。これにより、ウィジェットの有用性が制限されます。)。マッピングの問題を解決するために、テンプレートで予想されるローカル変数は、次のローカルメソッドによって作成されます(地元の人々は、ディレクティブ定義テンプレートの範囲であると推定されています):
スコープ:{タイトル: 'bind'、//タイトルを設定してデータバインディングonok: 'expression'、//デリゲートonok oncancel: 'expression'、//デリゲートoncancel関数ショーを作成します: 'アクセサ' //視認性のためにゲッター/セッター関数を作成します。}}}制御範囲にローカルプロパティを作成すると、2つの問題が発生します。
1。分離(属性分離?) - ユーザーがコントロールテンプレートに要素属性タイトルを設定するのを忘れた場合、タイトルは祖先範囲の属性「タイトル」にバインドされます(もしあれば)。これは予測不可能で望ましくありません。
2。Transclusion -翻訳されたDOMは、コントロールの地元の人々(範囲を分離する?)を表示できます。地元の人々は、輸血に縛られる必要があるプロパティをオーバーライドします。この例では、プラグイン内のタイトルプロパティは、TransClusionのタイトルプロパティを破壊します。
属性分離の欠如というこの問題を解決するには、この指令の孤立した範囲を定義する必要があります。 Isoloted Scopeは、子供の範囲からプロトタイプから継承されていません(なぜ子供の範囲ですか?親の範囲ではないのですか?)。
ただし、分離されたスコープには新しい問題が発生します。翻訳されたDOMがウィジェットの分離スコープの子である場合、何にもバインドできません。したがって、翻訳された範囲は、制御が前に作成された元の範囲の子スコープであり、ローカルプロパティの孤立した範囲を作成します。翻訳された範囲と分離されたスコープは、兄弟ノード(スコープツリー内)に属します。
これは少し予想外に複雑に思えるかもしれませんが、そうすることで、少なくともユーザーを制御し、開発者を制御することに驚きをもたらします。 (問題は解決されました)
したがって、最終的な指示定義は、ほぼ次のとおりです。
transclude:true、scope:{title: 'bind'、//タイトルを設定して、データバインディングonok: 'expression'、//関数oncancel: 'expression'、//デリゲートoncancel関数ショーを作成します。 //私はこれを試しましたが、失敗しました...読み続けてください}上記のコードをまとめて完全な例に巻き込もうとしました。直接コピーすると、予想される結果は達成されません。ただし、少し変更した後、プラグインを実行できます。
<!doctype html> <html ng-app = "dialog"> <head> <meta http-equiv = "content-type" content = "text/html; charset = utf-8"/> <title> directive-dialog </title> <meta content = "ie = edge = 1" htp-equcompatible ">" src = "../ angular.js" type = "text/javascript"> </script> </head> <body> <div ng-controller = "myctrl"> <button ng-click = "show = true"> <ダイアログ= "{{show}}" on-cancel = "show = fals; on-ok = "show = false; methodinparentscope();"> <! - 上記のcancelおよびon-okは、指令のアイソロート範囲によって参照されます。式に関数が含まれている場合、親スコープ(現在はmyctrlスコープ)に関数をバインドする必要があります - >ボディはここに行きます:username:{{username}}、title:{{title}}。 <ul> <! - ここでこのように再生できます〜名は親の範囲です - > <li ng-repeat = "name in name"> {{name}} </li> </ul> </dialog> </div> <script = "text/javascript"> var mymodule = angular.module( "dialog"、[]); mymodule.controller( "myctrl"、function($ scope){$ scope.names = ["name1"、 "name2"、 "name3"]; $ scope.show = false; $ scope.username = "lclao"; $ scope.title = "parent title"; $ scope = scope(inteing def( "親の範囲で演奏!!! ");};}); mymodule.directive( 'dialog'、function factory(){return {priority:100、template:['<div ng-show = "visible">'、 '<h3> {{title}} </h3>'、 '<div ng-transclude> </div>'、 '<buttin' <buttin '< ng-click = "oncancel()"> close </button> '、' </div> '、' </div> '、' </div> ']。ラッパー関数oncancelの形式: "&"、//ラッパー関数フォームを使用するダイアログタグのキャンセルプロパティの内容: "@" //ダイアログタグの目に見えるプロパティの値を指します}; </script> </body> </html>13。コンポーネントの作成
通常、複雑なDOM構造を介してディレクティブを置き換えることを期待しています(要素は配置されていますか?おそらく目的は、ディレクティブ内部複雑なポイントを作成することです。これにより、再利用可能なコンポーネントを使用して、アプリケーションを構築するための指令がショートカットになります。
再利用可能なコンポーネントの例は次のとおりです。
<!doctype html> <html ng-app = "zippymodule"> <head> <meta http-equiv = "content-type" content = "text/html; charset = utf-8"/> <title> zippymodule </title> <meta content = "ie =" type = "text/css"> .zippy {border:1px solid black;ディスプレイ:インラインブロック。幅:250px; } .zippy.opened> .title:before {content: ''; } .zippy.opened> .body {display:block; } .zippy.closed > .title:before { content: '► '; } .zippy.closed > .body { display: none; } .zippy > .title { background-color: black;色:白; padding: .1em .3em; cursor: pointer; } .zippy > .body { padding: .1em .3em; } </style> <script src="../angular.js" type="text/javascript"></script></head><body> <div ng-controller="MyCtrl"> Title: <input ng-model="title" type="text"><br/> Text: <textarea ng-model="text"></textarea> <hr/> <div zippy-title="Details: {{title}}...">{{text}}</div> </div> <script type="text/javascript"> var myModule = angular.module("ZippyModule", []); myModule.controller("MyCtrl", function ($scope) { $scope.title = "Here is the title"; $scope.text = "Here is the content... "; }); myModule.directive('zippy', function () { return { template: '<div>' + ' <div>{{title}}</div>' +//This title belongs to the property of the current direct isolate scope ' <div ng-transclude></div>' + //What is here, what is obtained is the property of the parent scope '</div>', replace:true, transclude: true, restrict:'C', scope:{ title:"@zippyTitle"//Bind the zippy-title attribute on the directive element}, link:function(scope,element,attrs) { var title = angular.element(element.children()[0]), opened = false; title.bind("click", toogle); element.addClass("closed"); function toogle() { opened = !opened; element.removeClass(opened ? "closed" : "opened"); element.addClass(opened ? "opened" : "closed"); } } }; }); </script></body></html>