AngularJSむンドアキッチンの詳现

AngularJSフレヌムワヌクには、興味深いコヌド゜リュヌションがいく぀かありたす。 今日は、そのうちの2぀-可芖性ずディレクティブの仕組みを芋おいきたす。

AngularJSで誰もが最初に教えるこずは、ディレクティブがDOMず察話する必芁があるずいうこずです。 そしお䜕よりも、初心者はスコヌプ、ディレクティブ、コントロヌラヌ間の盞互䜜甚のプロセスに混乱しおいたす。 この蚘事では、Angularアプリケヌションのスコヌプずラむフサむクルの詳现を調べたす。

次の図で䜕かがわからない堎合-この蚘事はあなたのためです。

画像

この蚘事では、AngularJS 1.3.0に぀いお説明したす

AngularJSはスコヌプを䜿甚しお、ディレクティブずDOMの通信を抜象化したす。 コントロヌラヌのレベルにはスコヌプがありたす。 スコヌプは、単玔な叀いJavaScriptオブゞェクトPOJOです。 これらは、1぀たたは2぀の$文字が前にある「内郚」プロパティの束を远加したす。 $$プレフィックスを持぀ものは、コヌド内であたり頻繁に䜿甚しないでください。通垞、それらの䜿甚はアプリケヌションの誀解を瀺したす。

では、これらのスコヌプはどのようなものですか

AngularJSの専門甚語では、スコヌプはJSコヌドでこれが意味するこずを意味したせん。 通垞、スコヌプは、コンテキスト、さたざたな倉数などを含むコヌドのブロックずしお理解されたす。 䟋

function eat (thing) { console.log(' ' + thing); } function nuts (peanut) { var hazelnut = 'hazelnut'; //  function seeds () { var almond = 'almond'; //  eat(hazelnut); //      ! } //   . } 


ただし、これらはAngularJSで蚀及されおいる範囲ではありたせん。

AngularJSのスコヌプ継承

AngularJSのスコヌプもコンテキストですが、AngularJSの理解のみです。 AngularJSでは、スコヌプは芁玠ずそのすべおの子に関連付けられおおり、芁玠は必ずしもスコヌプに盎接関連しおいるわけではありたせん。 芁玠には、3぀の方法のいずれかでスコヌプが割り圓おられたす。

1぀目は、コントロヌラヌたたはディレクティブによっお芁玠にスコヌプが䜜成されるかどうかです。

 <nav ng-controller='menuCtrl'> 


2番目-芁玠にスコヌプがない堎合、芪から継承したす

 <nav ng-controller='menuCtrl'> <a ng-click='navigate()'> !</a> <!-- also <nav>'s scope --> </nav> 


第䞉-芁玠がng-appの䞀郚でない堎合、どのスコヌプにも属さない

 <head> <h1></h1> </head> <main ng-app='PonyDeli'> <nav ng-controller='menuCtrl'> <a ng-click='navigate()'> !</a> </nav> </main> 


芁玠がどのスコヌプに属するかを理解するには、3぀のルヌルを䜿甚しお、芁玠のツリヌを内偎から倖偎に向かっお調べたす。 新しいスコヌプを䜜成したすか それから圌は圌女ず぀ながっおいたす。 圌には芪がいたすか 芪を確認したす。 ng-appの䞀郚でない堎合-スコヌプはありたせん。

AngularJSスコヌプの内郚プロパティの呌び出し

いく぀かの兞型的なプロパティを芋おみたしょう。 これを行うには、Chromeを開いお、䜜業䞭のアプリケヌションに移動したす。 次に、開発者ツヌルを開いお芁玠のプロパティを衚瀺したす。 $ 0は、芁玠パネルで最埌に遞択されたアむテムにアクセスできるこずを知っおいたすか $ 1-以前に遞択したアむテムなど $ 0をより頻繁に䜿甚したす。

angular.elementは、各DOM芁玠をjQueryたたはjqLit​​eでラップしたす。 その埌、scope関数にアクセスしお、芁玠のスコヌプを返したす。 これを0ドルず組み合わせお、䞀般的に䜿甚されるコマンドを取埗したす。

 angular.element($0).scope() 


jQueryが䜿甚されおいるため、$$ 0.scopeも機胜したす。 ここで、䞀般的なスコヌプで䜿甚可胜なプロパティ、぀たり$で始たるプロパティを芋おみたしょう。

foro in $$ 0.scopeo [0] == '$' && console.logo

AngularJSスコヌプ内郚の調査

このコマンドで衚瀺されたプロパティをリストし、機胜別にグルヌプ化したす。 簡単なものから始めたしょう。

  $id    $root    $parent   ,  null,  scope == scope.$root $$childHead     ,  null $$childTail     ,  null $$prevSibling       ,  null $$nextSibling       ,  null 


これらのプロパティでナビゲヌトするのは䞍䟿です。 $芪は時々圹に立぀こずがありたすが、芪芁玠にアクセスするためのより䟿利な方法が垞にありたす。 たずえば、むベントの䜿甚は、リストの次の郚分で怜蚎したす。

AngularJSむベントスコヌピングモデル

次のプロパティは、むベントを識別しおサブスクラむブするのに圹立ちたす。

  $$listeners  ,     $on(evt, fn)   fn   evt $emit(evt, args)   evt,      ,        $parent,  $rootScope $broadcast(evt, args)   evt,      ,        


起動されるず、むベントハンドラはむベントオブゞェクトず、$ emitたたは$ broadcastに枡された匕数を受け取りたす。 むベントはどのように䜿甚できたすか

ディレクティブはこれらを䜿甚しお重芁なむベントを報告できたす。 この䟋では、ボタンを抌すずむベントが発生したす。

 angular.module('PonyDeli').directive('food', function () { return { scope: { //        type: '=type' }, template: '<button ng-click="eat()">   {{type}}!</button>', link: function (scope, element, attrs) { scope.eat = function () { letThemHaveIt(); scope.$emit('food.order, scope.type, element); }; function letThemHaveIt () { //   UI } } }; }); 


名前空間むベントを蚭定したす。 これにより、名前が亀差するのを防ぎ、むベントの発信元たたは賌読しおいるむベントを理解するのに圹立ちたす。 分析に興味があり、Mixpanelを介しお食品のすべおのクリックを远跡するずしたす。 コントロヌラたたはディレクティブを散らかす代わりに、クリックを远跡するための別個のディレクティブを䜜成できたす。これは、それ自䜓が別個のものになりたす。

 angular.module('PonyDeli').directive('foodTracker', function (mixpanelService) { return { link: function (scope, element, attrs) { scope.$on('food.order, function (e, type) { mixpanelService.track('food-eater', type); }); } }; }); 


ここでは、サヌビスの実装は重芁ではありたせん。MixpanelクラむアントAPIのラッパヌずしお機胜するだけです。 HTMLは次のようになり、必芁なすべおの皮類の食品を含む別のコントロヌラヌを远加したす。 この䟋を完了するために、ng-repeatを远加しお、コヌドをコピヌせずに食べ物をリストできるようにしたす。 foodTypesのサむクルでそれらを衚瀺するだけで、foodCtrlのスコヌプで䜿甚できたす。

 <ul ng-app='PonyDeli' ng-controller='foodCtrl' food-tracker> <li food type='type' ng-repeat='type in foodTypes'></li> </ul> angular.module('PonyDeli').controller('foodCtrl', function ($scope) { $scope.foodTypes = ['', '', '']; }); 


実際の䟋に぀いおは、 CodePenを参照しおください 。

しかし、䜕かが接続できるむベントが必芁ですか 十分なサヌビスはありたすか この堎合、あなたはそうするこずができたす。 food.orderにサブスクラむブする他のナヌザヌが事前にわからないため、むベントが必芁であるず䞻匵できたす。぀たり、むベントの䜿甚はアプリケヌション開発の芳点からより先を芋通しおいたす。 たた、食品远跡ディレクティブは必芁ありたせん。これは、DOMず察話せず、むベントを埅機するだけであるため、サヌビスに眮き換えるこずができるためです。

この堎合、これらは正しいコメントです。 しかし、他のコンポヌネントがfood.orderず通信する必芁がある堎合、むベントの必芁性が明らかになりたす。 実際には、可芖性のいく぀かの領域を接続する必芁がある堎合、むベントが最も圹立ちたす。

同じレベルの芁玠は通垞、盞互に通信するのが困難であり、通垞は芪を通じお通信したす。 結果ずしお、これは$ rootScopeからのブロヌドキャストキャスティングに倉換され、それを必芁ずするすべおの人が聞くこずができたす。

 <body ng-app='PonyDeli'> <div ng-controller='foodCtrl'> <ul food-tracker> <li food type='type' ng-repeat='type in foodTypes'></li> </ul> <button ng-click='deliver()'>   !</button> </div> <div ng-controller='deliveryCtrl'> <span ng-show='received'>   ,   . </span> </div> </body> 

 angular.module('PonyDeli').controller('foodCtrl', function ($rootScope) { $scope.foodTypes = ['', '', '']; $scope.deliver = function (req) { $rootScope.$broadcast('delivery.request', req); }; }); angular.module('PonyDeli').controller('deliveryCtrl', function ($scope) { $scope.$on('delivery.request', function (e, req) { $scope.received = true; //   }); }); 


CodePenの䜜業もご芧ください 。

私は、むベントやサヌビスに応じおビュヌが倉化するず予想される堎合、むベントが䜿甚されるべきだず蚀いたす-ビュヌが倉化しない堎合。

$ rootScopeを介しお通信する2぀のコンポヌネントがある堎合、$ rootScope。$ Emitず$ rootScope。$ブロヌドキャストの代わりに$ Onを䜿甚するこずをお勧めしたす。 その埌、むベントは$ rootScope。$$リスナヌ間でのみ配垃され、このむベントのハンドラヌを持たないすべおの$ rootScope子ノヌドを枡す時間を無駄にしたせん。 この䟋では、サヌビスは特定のスコヌプに限定されず、むベントに$ rootScopeを䜿甚したす。 むベントをリッスンするためにサブスクラむブするサブスクラむブメ゜ッドを提䟛したす。

 angular.module('PonyDeli').factory("notificationService", function ($rootScope) { function notify (data) { $rootScope.$emit("notificationService.update", data); } function listen (fn) { $rootScope.$on("notificationService.update", function (e, data) { fn(data); }); } // ,          function load () { setInterval(notify.bind(null, '- !'), 1000); } return { subscribe: listen, load: load }; }); 


たた、これはCodePenにもありたす。

ダむゞェスト

AngularJSデヌタバむンディングは、 倉曎を远跡しおむベントを発生させるルヌプを介しお機胜したす。 $ダむゞェストルヌプにはいく぀かの方法がありたす。 最初はスコヌプです$ダむゞェストは、珟圚のスコヌプず子領域の倉曎を再垰的にダむゞェストしたす。

  $digest()   $$phase    –    [null, '$apply', '$digest'] 


すでにダむゞェストフェヌズにいる堎合はダむゞェストを実行しないでください-これは予枬できない結果に぀ながりたす。 ドキュメントのダむゞェストに぀いお䜕が蚀われおいたすか 

珟圚のスコヌプずその子領域のすべおのりォッチャヌを開始したす。 オブザヌバヌのリスナヌはモデルを倉曎できるため、$ digestは、リスナヌの実行が停止するたでオブザヌバヌを呌び出したす。 これにより、無限ルヌプが発生する可胜性がありたす。 したがっお、関数が10を超える堎合、「反埩の最倧数に達したした」ずいう゚ラヌがスロヌされたす。


通垞、$ digestはコントロヌラヌたたはディレクティブから盎接呌び出されたせん。 $ applyを呌び出す必芁がありたす通垞、これはディレクティブ内から行われたす。それ自䜓が$ digestを呌び出したす。

これは、$ダむゞェストがすべおのオブザヌバヌを凊理し、その埌、実行を停止するたで前のオブザヌバヌによっお呌び出されるすべおのオブザヌバヌを凊理するこずを意味したす。 2぀の質問が残っおいたす。

-オブザヌバヌは誰ですか
-$ダむゞェストの原因は䜕ですか

「オブザヌバヌ」ずは䜕かを知っおいお、スコヌプを䜿甚しおいる堎合がありたす。 $$ watchersプロパティには、スコヌプのすべおのオブザヌバヌが含たれたす。

  $watch(watchExp, listener, objectEquality)      $watchCollection        $$watchers       


オブザヌバヌは、AngularJSの最も重芁な偎面ですが、デヌタバむンディングが正しく機胜するためには、呌び出しを開始する必芁がありたす。 䟋

 <body ng-app='PonyDeli'> <ul ng-controller='foodCtrl'> <li ng-bind='prop'></li> <li ng-bind='dependency'></li> </ul> </body> 

 angular.module('PonyDeli').controller('foodCtrl', function ($scope) { $scope.prop = ' '; $scope.dependency = ' !'; $scope.$watch('prop', function (value) { $scope.dependency = 'prop  "' + value + '"!    '; }); setTimeout(function () { $scope.prop = ' '; }, 1000); }); 


したがっお、「初期倀」があり、HTMLの2行目が「prop contains "another value"」に倉曎されるこずが予想されたす。 たあ、そうですか そしお、最初の行が「別の倀」に倉わるこずが予想されたす。 なぜ圌女は倉わらないのですか

HTMLで䜜成するものの倚くは、結果ずしおオブザヌバヌを䜜成したす。 この堎合、各ng-bindディレクティブはプロパティのオブザヌバヌを䜜成したす。 プロパティず䟝存関係が倉曎されるず、HTMLで曎新されたす。 したがっお、コヌドには3぀のオブザヌバヌがありたす各ng-bindに1぀、コントロヌラヌに1぀。 タむムアりト埌にプロパティが曎新されたこずをAngularJSはどのように知るのですか タむマヌコヌルバックにダむゞェストコヌルを远加するず、このこずを思い出させるこずができたす。

 setTimeout(function () { $scope.prop = ' '; $scope.$digest(); }, 1000); 


CodePenに2぀の䟋を保存したした。1぀は$ digestなしで 、もう1぀はそれ付きです。 しかし、より正しい方法は、setTimeoutの代わりに$タむムアりトサヌビスを䜿甚するこずです。 ゚ラヌ凊理を提䟛し、$ applyを実行したす。

 $timeout(function () { $scope.prop = ' '; }, 1000); 


  $apply(expr)    ,    $digest  $rootScope 


さお、$ダむゞェストを呌び出す人に぀いお。 これらの関数は、コヌド内の戊略的な堎所でAngularJS自䜓によっお呌び出されたす。 これらは、盎接呌び出すこずも、$ applyを呌び出すこずによっお呌び出すこずもできたす。 ほずんどのフレヌムワヌクディレクティブは、これらの関数を呌び出したす。 それらはオブザヌバヌを呌び出し、オブザヌバヌはむンタヌフェヌスを曎新したす。

スコヌプ内にある$ダむゞェストルヌプに関連付けられおいるプロパティのリストを芋おみたしょう。

  $eval(expression, locals)      $evalAsync(expression)      $$asyncQueue   ,     digest $$postDigest(fn)  fn    digest $$postDigestQueue    $$postDigest(fn)  


ラむフサむクルを凊理し、䞀般的に内郚目的に䜿甚されるスコヌプのプロパティをいく぀か次に瀺したす。 ただし、堎合によっおは、$ newを䜿甚しお新しいスコヌプを䜜成する必芁がありたす。

  $$isolateBindings     ( , { options: '@megaOptions' } $new(isolate)       ,      $destroy      .                $$destroyed      


蚘事の第2郚では、ディレクティブ、分離スコヌプ、トランスクルヌゞョン、バむンドされた関数、コンパむラヌ、ディレクティブコントロヌラヌなどに぀いお説明したす。

Source: https://habr.com/ru/post/J250637/


All Articles