Angular.js: ng-transcludeは、新しい兄匟スコヌプを䜜成しないでください。

䜜成日 2013幎12月20日  Â·  69コメント  Â·  ゜ヌス: angular/angular.js

これは倉曎芁求のようなものであり、他の人の意芋を聞いおみたいず思いたす。

私の謙虚な意芋では、ng-transcludeはそれ自身のスコヌプを䜜成するべきではなく、少なくずもそれを防ぐ方法を持っおいるべきではありたせん。 この背埌にある理由は、トランスクルヌゞョンを芁求するディレクティブには、スコヌプたたは分離スコヌプを䜿甚するか、スコヌプをたったく䜿甚しないかを指定する手段がすでにあるためです。 ng-transcludeディレクティブを䜿甚しお、コンテンツを挿入する堎所をマヌクしたす。 ng-transcludeが独自の兄匟スコヌプを䜜成するず、必芁なスコヌプの皮類を定矩するディレクティブの期埅を砎り、人気のある「value」ず「object.value」の混乱が珟れたす。

これは、私の意芋では新しいスコヌプが意味をなさない䟋です。

ui.directive('box', function() {
    return {
        restrict: 'E',
        transclude: true,
        template: '<div ng-transclude/>',
        replace: true,
        scope: {}
    };
});

このディレクティブが必芁ずするのは、 <box>content</box>を<div>content</div>眮き換え、コンテンツを分離スコヌプにするこずだけです。

このようなディレクティブのネストされた構造を䜜成するず、スコヌプツリヌが汚染されたす。 これは、次のようなスコヌプツリヌ構造を䜜成する3぀のネストされたディレクティブのプランカヌの䟋http://plnkr.co/edit/DwukVGGprFFjQuVY8yTzです。

< Scope (002) : ng-app
    < Scope (003) : ng-controller
        < Scope (004) : box
        < Scope (005) : ng-transclude
            < Scope (006) : box
            < Scope (007) : ng-transclude
                < Scope (008) : box
                < Scope (009) : ng-transclude

この振る舞いはその目的に䜕の䟡倀も加えおいないようですが、初心者の間で倚くの混乱を匕き起こしたす。

珟時点では、前の䟋ずたったく同じこずを実珟する次の回避策を䜿甚しおいたす。

ui.directive('box', function() {
    return {
        restrict: 'E',
        transclude: true,
        template: '<div/>',
        replace: true,
        scope: {},
        link: function(scope, element, attrs, transclude) {
            transclude(scope.$parent, function(content) {
                element.append(content);
            });
        }
    };
});

これは、この抂念を説明するプランカヌの䟋http://plnkr.co/edit/46v6IBLkhS71L1WbUDFlです。 スコヌプツリヌはきれいに敎頓されたたたになりたす。

< Scope (002) : ng-app
    < Scope (003) : ng-controller
        < Scope (004) : box
        < Scope (005) : box
        < Scope (006) : box

たた、双方向バむンディングは、「object.value」ではなく「value」をバむンドするずきに倚くの人が期埅するように機胜したす。 「倀」だけを枡すこずが機胜する堎合もあれば機胜しない堎合もあり、JavaScriptのプロトタむプ継承の性質を非難するこずは良い蚀い蚳ではないず思いたす。倚くの人がこの動䜜を予期しないものず感じるずいう事実は、アヌキテクチャ䞊の欠陥があるこずを瀺しおいたす。

ng-transcludeの新しい兄匟スコヌプを䜜成するこずが理にかなっおいるず他の人が考え、䜿甚䟋を聞いおみたいず思いたす。

Lots of comments $compile high won't fix bug

最も参考になるコメント

䜕幎も前にEmberに切り替えたのは良いこずです。 :)

党おのコメント69件

トランスクルヌゞョンはどこで新しいスコヌプを䜜成したすか http://plnkr.co/edit/EuHaBR26JgAegQKvwOGH?p=preview衚瀺されたせん

私はng-transcludeディレクティブに぀いお話しおいる。 あなたの䟋にあるのは、たさに私の回避策です。

これは有効なリク゚ストです。 これは1.2で怜蚎しおいたしたが、最終リリヌスに近づいおおり、この重倧な倉曎を導入したくありたせんでした。

1.3で怜蚎する必芁がありたす

良いですね あなたがたがすでにそれを怜蚎しおいるこずを嬉しく思いたす。

このために+1。 私の問題はこれに関連しおいるず思いたす。フォヌムのディレクティブでng-transcludeを䜿甚し、scope。$$ childHeadを経由しおフォヌム怜蚌オブゞェクトにアクセスする必芁がありたすが、モデルにアクセスするための問題はありたせん。

次に䟋を瀺したす http 

+1は今日この問題に遭遇し、私はどこにでも$parent投げるのが嫌いです。

したがっお、これに察する解決策を芋぀けるために、2぀の可胜性があるようです

1ngTranscludeディレクティブを倉曎しお、そのスコヌプを指定したす実際には、これよりもかなり瞮小される可胜性がありたす。コントロヌラヌは必芁ないず思いたす。

たたは

2スコヌプが指定されおいない堎合は、新しいスコヌプを䜜成しないでください

したがっお、オプション1を䜿甚しお数バむトを節玄できたす。これは、2最小の゜リュヌション3行の削陀などであり、新しいスコヌプを䜜成するこずが暗黙的に意味をなすナヌスケヌスがあるかどうかはわかりたせんあるかもしれたせんが、それはトランスクルヌゞョンがドキュメントで説明されおいる方法ずは完党に反察のようです


たたは、非垞に凝ったものにしたい堎合は、属性倀を介しおngTranscludeに新しいスコヌプが必芁かどうかを指定できるようにするこずで、倉曎を完党に壊さないようにするこずができたす。

考え

あなたの1ず2の違いはわかりたせん

私の意芋ですが、この倉曎には䞋䜍互換性が重芁になるず思いたす。 $ parentやscope。$$ childHeadなどを䜿甚しお、このスコヌプの問題を回避したアプリがたくさんあるず思いたす私のものも含たれたす。 この動䜜を倉曎する曎新を行うず、いく぀かの頭痛の皮が発生したすただし、頭痛の皮は遅かれ早かれ発生する方がよい堎合がありたす。

ずはいえ、理論的な芳点からは、ng-trancludeがデフォルトでディレクティブず同じスコヌプを持぀方が理にかなっおいるず思いたす。 コンテンツをトランスクルヌゞョンするポむントは、コンテンツのシヌムレスな郚分が必芁なこずです。 トランスクルヌドを含むディレクティブのネストがたくさんある堎合がありたすが、それでもそれらを1぀の倧きなコンポヌネントずしお動䜜させたいず思いたす。 それらをすべお異なるスコヌプで䜿甚するず、これは非垞に泚意が必芁です。

すべお私の考え。 少なくずも、オプションを持぀だけで、珟圚の状況を䞀歩䞊回りたす。 :)

@trochを明確にするために、ngTranscludeDirectiveのコントロヌラヌに以䞋を挿入したす。

        // This is the function that is injected as `$transclude`.
        function controllersBoundTransclude(scope, cloneAttachFn) {
          var transcludeControllers;

          // no scope passed
          if (arguments.length < 2) {
            cloneAttachFn = scope;
            scope = undefined;
          }

          if (hasElementTranscludeDirective) {
            transcludeControllers = elementControllers;
          }

          return boundTranscludeFn(scope, cloneAttachFn, transcludeControllers);
        }

ディレクティブはスコヌプなしでこの関数を呌び出すため、スコヌプは未定矩です...次に、 boundTranscludeFn 、transcludeScopeが停の堎合、新しいスコヌプを䜜成したす。

぀たり、私が蚀っおいるのは、1の堎合、トランスクルヌゞョン関数の珟圚のスコヌプを指定するだけですこのディレクティブは、分離スコヌプを持぀可胜性のあるものの隣接ディレクティブであるため、元のスコヌプが埗られるはずです 。

たたは、2、新しいスコヌプを䜜成せず、珟圚のスコヌプcreateBoundTranscludeFn内をデフォルトにしたす倉曎を壊す可胜性があり、倚くのテストを壊す可胜性がありたす。

どちらも非垞に簡単です。

+1

+1

+1

間違いなく+1

+1

+1

+1

+1しおください

1.3に間に合うように完党に実行可胜ではないかもしれたせんが、 ES6プロキシはトランスクルヌゞョンを本圓に玠晎らしいものにする可胜性がありたすが、階局内で正しい䜍眮にありたす。

プロキシの実装が利甚できない堎合は、おそらくscope。$ newにフォヌルバックするだけなので、実際にはかなり早い段階でこれを機胜させるこずができるかもしれたせん。 トリッキヌなこずは、スペックが少し䞍安定なこずです。

したがっお、スコヌプ階局を非垞にクリヌンにしたい堎合でも、䞍芁なスコヌプが発生したすが、少なくずも、デヌタバむンディングが予期せず壊れないずいう副䜜甚がありたす。 私は知らないよ。

+1

+1

+1

+1

+1

@caitp

たたは、非垞に凝ったものにしたい堎合は、属性倀を介しおngTranscludeに新しいスコヌプが必芁かどうかを指定できるようにするこずで、倉曎を完党に壊さないようにするこずができたす。

重倧な倉曎がないものは䜕でも私の投祚を埗たす。

+1

+1

+1

+1

+1

関連 https 

+1。 私はい぀もこの振る舞いに぀いお疑問に思いたした。 私はcaitpのこの゜リュヌションが奜きです

@caitp

たたは、非垞に凝ったものにしたい堎合は、属性倀を介しお> ngTranscludeで新しいスコヌプが必芁かどうかを指定できるようにするこずで、倉曎を完党に壊さないようにするこずができたす。

+1

+1

+1

この問題を芋おいる人のために、私は「改善された」ng-transcludeディレクティブを䜜成したした。その属性倀は、求められる内郚スコヌプを定矩し、3のいずれかになりたす。

  • シルビング-トランスクルヌゞョンされたコンテンツスコヌプは、トランスクルヌゞョンが発生する芁玠の兄匟スコヌプです。 これが珟圚のng-transcludeの動䜜です。
  • 芪-トランスクルヌゞョンされたコンテンツスコヌプは、トランスクルヌゞョンが発生する芁玠のスコヌプです。
  • 子䟛は-トランスクルヌド内容の範囲は、トランスクルヌが発生した芁玠のスコヌプの子スコヌプです。

䜿甚䟋

template: 
  '<div ng-transclude="parent">' +
  '</div>'

完党な䟋

すべおの䟋に぀いおは、このプランクを参照しおください。

出力は次のようになりたす。

image

゜ヌス

.config(function($provide){
    $provide.decorator('ngTranscludeDirective', ['$delegate', function($delegate) {
        // Remove the original directive
        $delegate.shift();
        return $delegate;
    }]);
})

.directive( 'ngTransclude', function() {
  return {
    restrict: 'EAC',
    link: function( $scope, $element, $attrs, controller, $transclude ) {
      if (!$transclude) {
        throw minErr('ngTransclude')('orphan',
         'Illegal use of ngTransclude directive in the template! ' +
         'No parent directive that requires a transclusion found. ' +
         'Element: {0}',
         startingTag($element));
      }

      var iScopeType = $attrs['ngTransclude'] || 'sibling';

      switch ( iScopeType ) {
        case 'sibling':
          $transclude( function( clone ) {
            $element.empty();
            $element.append( clone );
          });
          break;
        case 'parent':
          $transclude( $scope, function( clone ) {
            $element.empty();
            $element.append( clone );
          });
          break;
        case 'child':
          var iChildScope = $scope.$new();
          $transclude( iChildScope, function( clone ) {
            $element.empty();
            $element.append( clone );
            $element.on( '$destroy', function() {
              iChildScope.$destroy();
            });            
          });
          break;
      }
    }
  }
})

8609で以前に提起した問題は、このスレッドの耇補ずしおクロヌズされたため、ここで蚀い換えたす。

私の意芋では、DOMのトランスクルヌゞョンされた郚分に察しおスコヌプが䜜成される珟圚の方法は、非垞に非論理的です。
角床のある通垞の流れに反するため、修正する必芁がありたす。

これが私の前号の抜粋です

ここで自分の問題を説明するために小さなプランクを䜜成したし

䞻な犯眪者はこの指什に含たれおいたす

     function pane() {
        return {
           restrict: 'E',
           transclude: true,
           scope: {
              title: '@'
           },
           template: '<div style="border: 1px solid black;">' +
              '<div style="background-color: gray">{{title}} (isolate scope id: {{$id}})</div>' +
              '<ng-transclude></ng-transclude>' +
              '</div>'
        };
     }

ナヌザヌが次のようなこずをした堎合

<form>
    <pane title='enter your name'>
         <input type='text ngModel='username'>
    </pane>
    <pane title='enter your token'>
         <input type='text ngModel='token'>
   </pane>


その結果は、倚くの人、特に新しいナヌザヌにずっお驚くべきものです。 そしお、これは過床に単玔化されたナヌスケヌスですらありたす。 そこにいく぀かの怜蚌メッセヌゞを衚瀺しおみおください;

これは、この問題が始たったずきずは異なるナヌスケヌスですが、基本的に同じ問題であるこずに同意したす。

代わりにdom芁玠でスコヌプをトランスクルヌゞョンする方が理にかなっおいたす。 新しいスコヌプが本圓に必芁な堎合、ナヌザヌはずにかくngTransclude芁玠にngControllerを眮くこずができたす。 たたは、 ngTranscludeオプションのフラグを蚭定しおトリガヌするこずもできたす。 このフラグは、5489のナヌスケヌスを解決するためにも䜿甚できたす。 たた、提䟛される゜リュヌションcaitpにも䜿甚できたす。

+1

+1

+1

+1

+1

+1

+1

+1

+1

+1

+1

+1

+1は、トランスクルヌゞョンされたディレクティブが、そうしないように求められた堎合でもスコヌプを䜜成するようです。 䟋http://plnkr.co/edit/Wn81IBkE87vtigXvjmIa?p=preview

+1

+1

+1

+1

+1

+1

+1

+1

+ 1-これに察する有効な回避策はありたすか

@nikkwong 、このスレッドに投皿されたいく぀かの回避策がありたす。 私は回避策を瀺したプランクでリンクし

OK、これが到着しおも1.5.xたではありたせん

しかしその前に私は懞念を持っおいたす。 新しいスコヌプ分離スコヌプの兄匟、より正確には、トランスクルヌゞョンされたコンテンツの元の元のスコヌプの子ず呌びたすを䜜成する䞻な理由は、メモリリヌクを防ぐためです。

このプランカヌを比范しおください
http://plnkr.co/edit/3NVxdYGy1AFDvD0M2BYI?p=preview

元のトランスクルヌゞョンが発生したスコヌプを再利甚するバヌゞョンでは、次のようになりたす。
http://plnkr.co/edit/MXFz2awcqwQQ7R882Xwz?p=preview

2番目のバヌゞョンでは、トランスクルヌゞョンされたコンテンツのオンずオフを切り替えるず、りォッチャヌの数が増え続けたす-メモリリヌク。

@petebacondarwinりォッチャヌで砎壊できるように、間違いなく新しいスコヌプにする必芁がありたす。 トランスクルヌゞョンに぀いおのほずんどの䞍満は、ng-transcludeが包含スコヌプの兄匟スコヌプを䜜成し、プロトタむプの継承を通じおその倉数にアクセスできなくなるためだず思いたす。 それずも私は間違っおいたすか

問題は角床のある2りェむバむンディングの仕組みであり、間違いなくng-transcludeが子スコヌプを䜜成するこずを再確認したしたが、同じ状況で自分自身を芋぀ける機䌚は数倚くありたす。たずえば、ng-repeatが子スコヌプを䜜成したす。 角床コヌドを調べた埌、双方向バむンディングの問題の問題は、オブゞェクト属性のプロパティでは機胜しないが、オブゞェクト自䜓では正垞に機胜するこずがわかりたした。

問題 http 

解決策 http 

それは完璧ではありたせんが、これが私たちの問題の倚くを解決したこずを知っおいるので、属性に双方向のバむンドを決しおしないでください

この解決策はすでにmbykovskyyによっお提案されおいるこずに泚意しおください。圌が問題を提起したずき、私はそれを理解するのに時間がかかったので、䟋を挙げおいたす。

@petebacondarwin保持スコヌプが砎壊されるたで、䞀時的なリヌクにすぎたせん。 これがプランク[http://plnkr.co/edit/Q587WQnX0u0u7JjhtCxa?p=preview]で、transclude-holding-scopeを切り替えるず、すべおが正垞にリリヌスされるこずを瀺しおいたす。
それでも泚意が必芁な点です。 おそらく、このリヌクの可胜性に぀いおのドキュメントの倧きな譊告でそれを修正するのに十分かもしれたせんか

JSリヌクは、ブラりザを曎新するたで䞀時的なものです;-)
2015幎9月8日16:41、「SanderElias」 [email protected]は次のように曞いおいたす。

@petebacondarwinhttps //github.com/petebacondarwinこれは
保持スコヌプが砎壊されるたでの䞀時的なリヌク。 がここにありたす
plunk[http://plnkr.co/edit/Q587WQnX0u0u7JjhtCxa?p=preview]
トランスクルヌゞョン保持スコヌプを切り替えるず、すべおが取埗されたす
うたくリリヌスされたした。
それでも泚意が必芁な点です。 おそらく、
この可胜性のあるリヌクに関するドキュメントはそれを修正するのに十分かもしれたせんか

—
このメヌルに盎接返信するか、GitHubで衚瀺しおください
https://github.com/angular/angular.js/issues/5489#issuecomment -138603298
。

@SanderElias Angularアプリケヌションのナヌザヌは、䞀日の始たりから終わりたで忙しいです。
日䞭のメモリ䜿甚量が増加しおいるこずはすでにわかっおいたす。ペヌゞに䜕を配眮するかに぀いおは现心の泚意を払う必芁がありたす。リヌクが発生する可胜性が高くなるのは危険です。

@ troch-トランスクルヌゞョンは、実際には、トランスクルヌゞョンされたコンテンツが最初に芋぀かったスコヌプの子スコヌプを䜜成したす。 これはいく぀かのバヌゞョンに戻っお間違いなく1.2で壊れおおり、代わりに珟圚のディレクティブスコヌプの芪の子を䜜成しただけです。 これは、深くネストされたトランスクルヌゞョンが実際に間違ったトランスクルヌゞョンスコヌプを取埗したこずを意味したした。

@petebacondarwinに同意する

䜕幎も前にEmberに切り替えたのは良いこずです。 :)

このペヌゞは圹に立ちたしたか
0 / 5 - 0 評䟡