AngularJS-ng-ifの仕組みを知っていますか?



少し前に、ng-ifディレクティブの動作について書きましたが、状態チェックに遭遇しましたが、今日は別の問題が発生しました。



プロジェクトには、ツールチップ、ポップオーバー、モーダルウィンドウなどの多くの要素があります。 皆さんはこれらの要素が何であるかを理解していると思うので、それらについてはお話ししません。 それらの多くでは、絶対配置が使用されます。 カスタムディレクティブを使用しなかった場合、問題はありません。すべてのモーダルウィンドウは本文の最後にあり、必要なときに表示されます。 しかし、これらの要素はすべてディレクティブとして宣言されているため、ディレクティブには相対的な位置決めなどの親があるため、位置決めに問題があります。



<div style="position: relative; overflow:hidden"> <button ng-click="visible = true">Greeting</button> <modal visible="visible"> Hello, Habr! </modal> </div>
      
      







モーダルウィンドウは、ブラウザウィンドウに対して相対的に配置する必要がありますが、この場合、親要素に対して相対的に配置されます。

この問題の最も簡単な解決策は、現在のディレクティブから要素を引き出すことです。



 module.directive('modal',[ '$rootElement', function( $rootElement ){ return { restrict: 'E', ... link: function(scope, element){ element.appendTo($rootElement); scope.$on('$destroy', function(){ element.remove(); }); ... } } }] });
      
      







つまり、現在のコンテキストから要素を選択し、それをアプリケーションのルート要素に挿入します。 ディレクティブが削除されると、要素が削除されます。 すべて問題ないように見えますが、 ng-if



ディレクティブをこのアプローチと一緒に使用するまで問題はありません。



ng-if



条件が負のng-if



DOM要素を完全に削除します。多くの人が知っていると思いますが、これがどのように起こるかを知っている人は多くありません。



ソースコードとウォッチャーの ng-if



属性自体は次のとおりです。

結果が正の場合、コメントが作成されdocument.createComment(' end ngIf: ' + $attr.ngIf + ' ');



変数block.clone



2つの値が配置されます。





ページのソースコードでは、ほとんどの場合、次のように表示されます。





このスクリーンショットでは、条件ng-if="!task.id"



は正であり、ディレクティブが宣言されているli要素はDOMツリー内にあり、コメントとの間です。 2番目の条件ng-if="validation.task.app_id"



は負であり、コメント間には何もありません。


結果が負の場合、子スコープを破棄し、要素削除します 。 そして、 getBlockElements関数で最も興味深いのは:

 /** * Return the DOM siblings between the first and last node in the given array. * @param {Array} array like object * @returns {DOMElement} object containing the elements */ function getBlockElements(nodes) { var startNode = nodes[0], endNode = nodes[nodes.length - 1]; if (startNode === endNode) { return jqLite(startNode); } var element = startNode; var elements = [element]; do { element = element.nextSibling; if (!element) break; elements.push(element); } while (element !== endNode); return jqLite(elements); }
      
      





説明からこの関数を明確にするのは、指定された配列の最初と最後のノード間のDOM兄弟を返すことです。

そして、この場合のノード引数は、私が説明した2つの要素の配列です。 つまり、関数は、 ng-if



ディレクティブが宣言されたメイン要素と終了コメントの間のすべての要素を返します。コメントが見つからなかった場合、メイン要素の後のすべての要素を返します。



たとえば、このようなテンプレート(#angle-application-アプリケーションのルート要素):

 <div id="angular-application"> ... <div style="position: relative; overflow: hidden"> <div style="position: absolute; right: 0; bottom: 0"> <modal ng-if="isFirstModal()" id="modal-1">...</modal> <modal ng-if="isSecondModal()" id="modal-2">...</modal> </div> <div style="position: absolute; left: 0; bottom: 0"> <popover ng-if="isFirstPopover()" id="popover-1">...</popover> <popover ng-if="isSecondPopover()" id="popover-2">...</popover> </div> </div> ... </div>
      
      





次のHTMLでコンパイルします。

 <div id="angular-application"> ... <div style="position: relative; overflow: hidden"> <div style="position: absolute; right: 0; bottom: 0"> <!-- ngIf: isFirstModal() --> <!-- end ngIf: isFirstModal() --> <!-- ngIf: isSecondModal() --> <!-- end ngIf: isSecondModal() --> </div> <div style="position: absolute; left: 0; bottom: 0"> <!-- ngIf: isFirstPopover() --> <!-- end ngIf: isFirstPopover() --> <!-- ngIf: isSecondPopover() --> <!-- end ngIf: isSecondPopover() --> </div> </div> ... <div id="popover-1" class="popover">...</div> <div id="modal-1" class="modal-window">...</div> <div id="modal-2" class="modal-window">...</div> <div id="popover-2" class="popover">...</div> </div>
      
      





つまり、上記のように、すべてのモーダルウィンドウとポップオーバーを使用しているため、ポジショニングに違反することはなく、レイアウトはアプリケーションの最後に移動しましたが、コメントは同じ場所に残りました。 そして今、のgetBlockElements関数 .- - #popover-1 , #modal-1 , #modal-2 , #popover-2 . ng-if="isFirstPopover()"



DOM .



:

:) . . , , , , . - , - ; . , , , ; ng-if . . , . , - enable; . , ng-if



, 600; , . : element.find('[append-to-root]').appendTo($rootElement);



ng-if



, :

<div ng-if="condition"> <my-custom-directive>...</my-custom-directive> </div>












All Articles