ホームページ  >  記事  >  ウェブフロントエンド  >  angularJs のディレクティブの不人気な属性の詳細な説明

angularJs のディレクティブの不人気な属性の詳細な説明

高洛峰
高洛峰オリジナル
2016-12-09 11:21:451002ブラウズ

NG を使用する場合、よく知られている属性についてはここでは紹介しません

1.multiElement

の機能です。命令のスコープを指定するもので、最も一般的に使用されるのは ng-repeat-start と ng-repeat-end です。

2.priority

命令の優先順位。優先順位が高いほど、命令がより早く実行されます。

3.ターミナル

優先度の低い命令の動作を許可するかどうか。true の場合、現在の命令と同じレベル以上の命令のみを実行できます。最も典型的なものは ngIf です

4.templateNamespace

宣言テンプレートの形式には svg、html、math の 3 つのオプションがあります

5.transclude

疑問を持つ人もいるかもしれませんが、transclude も人気のない属性ですか?実際、誰もが思っているほど、transclude についてよく知りません。transclude は非常に複雑な属性です。一般に、誰もが使用するのは true と false だけです。ここではこれら 2 つの属性については説明しません。ここで主に説明するのは、transclude:element についてです。一日中グーグル検索しましたが、この属性を正しく説明する方法が見つかりませんでした。 Google の回答は文書化されすぎていると思います。最後に、$transclude を勉強した後、この属性の機能が何であるかを理解しました。関数について話す前に、まず $transclude を理解しましょう

最後のパラメータは、命令のコンパイル期間またはリンク期間に関係なく、$transclude です。 ここでは、ソース コードがどのように定義されているかを実際に見ていきます。 ng1.5.3

function controllersBoundTransclude(scope, cloneAttachFn, futureParentElement, slotName) {
     var transcludeControllers;
     // No scope passed in:
     if (!isScope(scope)) {
      slotName = futureParentElement;
      futureParentElement = cloneAttachFn;
      cloneAttachFn = scope;
      scope = undefined;
     }
 
     if (hasElementTranscludeDirective) {
      transcludeControllers = elementControllers;
     }
     if (!futureParentElement) {
      futureParentElement = hasElementTranscludeDirective ? $element.parent() : $element;
     }
     if (slotName) {
      // slotTranscludeFn can be one of three things:
      // * a transclude function - a filled slot
      // * `null` - an optional slot that was not filled
      // * `undefined` - a slot that was not declared (i.e. invalid)
      var slotTranscludeFn = boundTranscludeFn.$$slots[slotName];
      if (slotTranscludeFn) {
       return slotTranscludeFn(scope, cloneAttachFn, transcludeControllers, futureParentElement, scopeToChild);
      } else if (isUndefined(slotTranscludeFn)) {
       throw $compileMinErr('noslot',
        'No parent directive that requires a transclusion with slot name "{0}". ' +
        'Element: {1}',
        slotName, startingTag($element));
      }
     } else {
      return boundTranscludeFn(scope, cloneAttachFn, transcludeControllers, futureParentElement, scopeToChild);
     }
    }

特に指摘しなければならない機能がもう1つあり、それは最後に返されるboundTranscludeFnメソッドです。 以下はそのソースコードです

​​
function createBoundTranscludeFn(scope, transcludeFn, previousBoundTranscludeFn) {
   function boundTranscludeFn(transcludedScope, cloneFn, controllers, futureParentElement, containingScope) {
 
    if (!transcludedScope) {
     transcludedScope = scope.$new(false, containingScope);
     transcludedScope.$$transcluded = true;
    }
 
    return transcludeFn(transcludedScope, cloneFn, {
     parentBoundTranscludeFn: previousBoundTranscludeFn,
     transcludeControllers: controllers,
     futureParentElement: futureParentElement
    });
   }

この2つのメソッドは何をしているのでしょうか?実際、現在の命令のノードのクローンを作成し、子スコープを生成します。クローン化されたノードは、transclude によって定義されます。属性が true の場合、命令テンプレートの ng-transclude が配置されている DOM ノードとその子ノードがクローン化されます。属性が要素の場合、テンプレート ノード全体のクローンを作成します。

これは 2 つの命令のコードです

​​
angular.module('MyApp', [])
      .directive('dropPanel', function() {
        return {
          transclude: 'element',
          replace: true,
          template: "<div class=&#39;drop-panel&#39;>" +
            "<span ng-transclude class=&#39;111&#39;></span>" +
            "</div>",
          link: function(scope, el, c, d, $transclude) {
            $transclude(function ngRepeatTransclude(clone, scope) {
              console.log(clone);
            })
 
          }
        }
      })
      .directive(&#39;dropPanel2&#39;, function() {
        return {
          transclude: true,
          replace: true,
          template: "<div class=&#39;drop-panel&#39;>" +
            "<span ng-transclude class=&#39;111&#39;></span>" +
            "</div>",
          link: function(scope, el, c, d, $transclude) {
            $transclude(function ngRepeatTransclude(clone, scope) {
              console.log(clone);
            })
          }
        }
      })

置換が結果の理解を妨げていると感じる場合は、コメントアウトして、コンソールに出力されたクローンを見ると、その役割を知ることができます。要素として宣言されたいわゆる transclude 属性 ここで、replace を開く目的は、DOM ノードをより明確に表示して結論を​​導くことです。上の図を読むと、コンパイル後の DOM ノードの違いがわかります。この 2 つは明確に区別されます。また、属性を「要素」として宣言する場合は、レンダリングする前に replace を true として宣言する必要があります。多くの情報を確認し、最終的にブレークポイントを使用して正しい結論に達しました。ブレークポイント追跡の結果、replace が宣言されていない場合、ngTransclude 命令は実行されないようです。このため、レンダリングが失敗します。次に、最終的な分析は、2 つの操作の DOM 要素が異なるということです。transclude を要素として宣言する場合、replace は true であり、取得される DOM ノードは transclude 属性を含むノード (子ノード) であり、それが false の場合です。 , 得られるものはそうではありません。transclude 属性を含むノード (親ノード) であり、ng 自体がそのノードを走査しないため、ngTransclude 命令の実行に失敗します

良いと思う視点を拝見しました。これはおそらく次のことを意味します: 機能上の考慮事項により、要素属性を使用する場合、通常はプレースホルダーとして機能します。このクローン作成関数は、実行する必要がある操作が DOM に追加される場合にのみ使用されます。 angularJs のディレクティブの不人気な属性の詳細な説明

この観点は良いと思います。ngrepeat についての多くの紹介文を読んだことがありますが、実際には、これは完全に正しいわけではありません。 use $scope.$new はサブスコープを生成しますが、この生成機能は $transclude 関数に任せられています。実際、ngrepeat のソースコードは $transclude を使用してサブスコープを生成し、DOM ノードを追加します。上記の点と同様です。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。