初心者向けのAngularjsディレクティブ。 パート1

私の意見では、ディレクティブはAngularjsの宣言スタイルの主要なハイライトです。 ただし、 ディレクティブ特化した Angularjsの公式ドキュメントのセクションでユーザーのコメントを開くと、 最も人気のあるものは次のようになります。 初心者のAngularjs開発者がそれを理解するのは困難です」(「ディレクティブの明確に構成された明確なドキュメントを書き直してください。 これに異議を唱えるのは難しく、ドキュメントはまだ湿っていて、ある時点で機能のロジックと本質を理解するために多大な努力をしなければなりません。 したがって、この章が誰かの時間を節約することを期待して、この章の私の無料の言い直しを提供し、コメントへのあなたのサポートと参加も期待しています。 さあ、行こう!



ディレクティブの書き方



Angularjsディレクティブは、次のように他のモジュール構成とともに設定されます。



angular.module('moduleName', []) .directive('directiveName', function () { /*-  */ }) .directive('anotherDirectiveName', function () { /*-  */ });
      
      





発表には2つのオプションがあります。 よりシンプルで強力な長いオプション。



ディレクティブを作成する簡単な方法



HTMLマークアップで指定するときに呼び出されるディレクティブを記述するために、最も単純なケースでは、ファクトリーによって返される関数(Linking Linkingと呼ばれますが、これについては後ほど説明します)を設定する必要があります。



 angular.module('moduleName', []) .directive('directiveName', function () { return function(scope,element,attrs){ } });
      
      





この関数は、次のパラメーターを受け入れます。



より詳細な例を使用してみましょう。 このようなディレクティブ( habra-habrを呼び出しましょう)を作成します。このディレクティブは2行を折り畳み、 呼び出されたレイアウト要素内に表示します。 この場合、1行をコントローラー変数( forExampleController )として設定し、2行目を同じタグで属性( habra )を渡します。 また、ディレクティブを呼び出すときにコントローラー変数の名前を決定する機能を予約します。



[ jsFiddle ]

 <div ng-app="helloHabrahabr"> <div ng-controller="forExampleController"> <input ng-model="word"> <span habra-habr="word" habra="Nehabra"></span> </div> </div>
      
      





 function forExampleController($scope) { $scope.word="Habrahabra" } angular.module('helloHabrahabr', []) .directive('habraHabr', function() { return function($scope, element, attrs) { /* ,       word,     attrs.habraHabr*/ $scope.$watch(attrs.habraHabr,function(value){ element.text(value+attrs.habra); }); } });
      
      





それだけです プリミティブ形式のディレクティブは準備ができています。 より詳細なフォームに進むことができます。



拡張オプション



完全な形式では、ディレクティブのタスクは次のとおりです。



 angular.module('moduleName', []) .directive('directiveName', function () { return { compile: function compile(temaplateElement, templateAttrs) { return { pre: function (scope, element, attrs) { }, post: function(scope, element, attrs) { } } }, link: function (scope, element, attrs) { }, priority: 0, terminal:false, template: '<div></div>', templateUrl: 'template.html', replace: false, transclude: false, restrict: 'A', scope: false, controller: function ($scope, $element, $attrs, $transclude, otherInjectables) { } } });
      
      





これらのプロパティはすべて非常に密接に関連しており、絡み合っています。 また、これを理解しやすくするために、特定のセマンティックグループでそれらを考慮することをお勧めします。



リンクとコンパイル


Linkメソッドは、ディレクティブファクトリが短いバージョンで返したまさにその機能です。 ここで、Angularjsではコンパイルプロセスが2つの段階に分かれていることを理解する必要があります。







そして同時に、最も単純なバージョンでも高度なバージョンでも、Linkメソッドは変数が既にマップされた後に実行されるため、 postLinkを正しく呼び出します。 いくつかの例を見てみましょう。



最初に、単純なディレクティブの例を拡張された方法で書き直すことをお勧めします。



[ jsFiddle ]

 angular.module('helloHabrahabr', []) .directive('habraHabr', function() { return { link:function($scope, element, attrs) { /* ,       word*/ $scope.$watch(attrs.habraHabr,function(value){ element.text(value+attrs.habra); } ); } } });
      
      





つまり、すべてが以前と同じように機能します。 タスクを複雑にし、フレーズをDOM element.text(...)との直接的な対話ではなく、補間"{{}}"ディレクティブ内に表示できます



[ jsFiddle ]

 angular.module('helloHabrahabr', []) .directive('habraHabrNotwork', function() { return { link:function($scope, element, attrs) { element.html("<div>{{"+attrs.habraHabrWork+"}}"+attrs.habra+"</div>"); } } }) .directive('habraHabrWork', function() { return { compile: function compile(templateElement, templateAttrs) { templateElement.html("<div>{{"+templateAttrs.habraHabrWork+"}}"+templateAttrs.habra+"</div>"); }, link: function (scope, element, attrs) { } } });
      
      





tamtakoe コメント後に更新された例



上記の例では、 habraHabrNotworkディレクティブ正しく機能しません。これは、ディレクティブ「{{}}」を変数とともにpostLinkに挿入するためです。つまり、コンパイルとリンクが既に完了している場合です。 つまり、Angularjsは、「{{}}」が強制可能なディレクティブであることすら知りません。



もう1つは、2番目のディレクティブです。 すべてが適切な場所にあるので、コンパイルの前にテンプレート "{{" + attrs.habraHabrNotwork + "+" + attrs.habra + "}}"を挿入すると、レンダリングに成功します。



コンパイル方法について詳しく見てみましょう。 postLink関数と、preとpostの2つのパラメーターを持つオブジェクトの両方を返すことができます。 preおよびpostは、それぞれpreLinkおよびpostLinkメソッドです。 メソッドの名前から、 リンク aの前後のメソッドについて話しているように見えるかもしれません。 ただし、これは完全に真実ではありません。これらの機能は、 LinkおよびDOMのchildrenディレクティブの前後に実行されます。 例:



[ jsFiddle ]

 <div ng-app="helloHabrahabr"> <div ng-controller="forExampleController"> <input ng-model="word"> <span habra-habr-work="word" habra="NehabraParent"> <span habra-habr-work="word" habra="NehabraChild"></span> </span> <pre>{{log}}</pre> </div> </div>
      
      







 function forExampleController($scope) { $scope.word="Habrahabra"; $scope.log=""; } angular.module('helloHabrahabr', []) .directive('habraHabrWork', function() { return { compile: function compile(templateElement, templateAttrs) { templateElement.prepend("<div>{{"+templateAttrs.habraHabrWork+"}}"+templateAttrs.habra+"</div>"); return { pre: function ($scope, element, attrs, controller) { $scope.log+=templateAttrs.habra +' preLink \n'; }, post: function ($scope, element, attrs, controller) { $scope.log+=templateAttrs.habra +' postLink \n'; } } } } });
      
      







これについては、一時停止することを提案します。 トピックが興味深い場合は、今後数日でスコープとテンプレートについての続編を書きます。



All Articles