スコープが制限されているディレクティブに関して、モデルのスコープとそのバインディングを理解するのに苦労しています。
ディレクティブのスコープを制限するということは、controller。$ scopeとdirective.scopeが同じものではなくなったことを意味します。ただし、ディレクティブテンプレート内またはhtml内のモデルの配置がデータバインディングにどのように影響するかについて混乱しています。私は非常に基本的なものを見逃していると感じています。先に進むには、これを理解する必要があります。
次のコードを使用します(ここを中心に: http://jsfiddle.net/2ams6/ )
JavaScript
var app = angular.module('app',[]);
app.controller('Ctrl',function($scope){
});
app.directive('testel', function(){
return {
restrict: 'E',
scope: {
title: '@'
},
transclude: true,
template: '<div ng-transclude>'+
'<h3>Template title: {{title}}</h3>' +
'<h3>Template data.title:{{data.title}}</h3>' +
'</div>'
}
});
HTML
<div ng-app='app'>
<div ng-controller="Ctrl">
<input ng-model="data.title">
<testel title="{{data.title}}">
<h3>Transclude title:{{title}}</span></h3>
<h3>Transclude data.title:{{data.title}}</h3>
</testel>
</div>
</div>
モデルは、テンプレート内の{{title}}
、およびトランスクルージョンの{{data.title}}
のみを更新します。 トランスクルージョンの{{title}}
やテンプレートの{{data.title}}
ではないのはなぜですか?
そのように入力をトランスクルージョン内に移動します(ここを中心に: http://jsfiddle.net/eV8q8/1/ ):
<div ng-controller="Ctrl">
<testel title="{{data.title}}">
<input ng-model="data.title">
<h3>Transclude title: <span style="color:red">{{title}}</span></h3>
<h3>Transclude data.title: <span style="color:red">{{data.title}}</span></h3>
</testel>
</div>
現在は、トランスクルード{{data:title}}
のみが更新されることを意味します。 テンプレート{{title}}
または{{data.title}}
のどちらでもない、または{{title}}
?をトランスクルードしない理由
そして最後に、そのように入力をテンプレート内に移動します(ここを中心に: http://jsfiddle.net/4ngmf/2/ ):
template: '<div ng-transclude>' +
'<input ng-model="data.title" />' +
'<h3>Template title: {{title}}</h3>' +
'<h3>Template data.title: {{data.title}}</h3>' +
'</div>'
現在は、テンプレート{{data.title}}
のみが更新されることを意味します。 もう一度、他の3つのバインディングはどうですか?
私は顔に私を見つめる明らかな何かがあり、私はそれを見逃していると思います。これを手に入れてくれたら、ビールを買うか、ポイントをあげるか、そういうものをあげる。どうもありがとう。
フィドルは3つのスコープを作成します。
ng-controller
のため、コントローラーCtrl
に関連付けられたスコープtransclude: true
が原因でディレクティブがトランスクルードされたスコープscope: { ... }
のため、ディレクティブはスコープを分離しますFiddle1では、テキストボックスに何かを入力する前に、次のものがあります。
スコープ003は、コントローラーに関連付けられたスコープです。テキストボックスにはまだ入力しなかったため、data
プロパティはありません。分離スコープ004では、title
プロパティが作成されましたが、空です。親スコープにはdata.title
プロパティがまだないため、空です。
テキストボックスにmy title
と入力すると、次のようになります。
コントローラースコープ003には新しいdata
オブジェクトプロパティがあり(これが黄色で表示されている理由です)、title
プロパティがmy title
に設定されています。分離スコーププロパティtitle
はdata.title
の内挿値に一方向データバインドされるため、値my title
も取得します(値は変更されたため黄色になります)。
トランスクルードされたスコープは、プロトタイプでコントローラースコープを継承するため、トランスクルードされたHTML内でangularはプロトタイプチェーンをたどり、親スコープで$scope.data.title
を見つけることができます(ただし$scope.title
はそこに存在しない)。
分離スコープは、独自のプロパティにのみアクセスできるため、プロパティtitle
のみにアクセスできます。
入力する前のfiddle2には、fiddle1と同じ画像があります。
my title
と入力した後:
新しいdata.title
プロパティが表示された場所に注意してください-トランスクルードされたスコープ上。分離スコープはまだコントローラースコープでdata.title
を探していますが、今回はそこにないので、そのtitle
プロパティ値は空のままです。
Fiddle3では、入力する前にfiddle1と同じ画像が表示されます。
my title
と入力した後:
分離スコープの新しいdata.title
プロパティが表示されていることに注目してください。他のスコープはどれも分離スコープにアクセスできないため、文字列my title
は他のどこにも表示されません。
Angular v1.2:の更新
変更により eed299a Angularは、トランスクルージョンする前にトランスクルージョンポイントをクリアするため、変更しない限り、Template title: ...
およびTemplate data.title: ...
パーツは表示されません。次のようなng-transclude
のみのテンプレート
'<h3>Template title: <span style="color:red">{{title}}</span></h3>' +
'<h3>Template data.title: <span style="color:red">{{data.title}}</span></h3>' +
'<div ng-transclude></div>'
以下のAngular v1.3の更新では、このテンプレートが変更されました。
Angular v1.3 +:の更新
Angular v1.3であるため、トランスクルードされたスコープは、コントローラースコープの子ではなく、ディレクティブの分離スコープの子になります。したがって、fiddle1で何かを入力する前に:
このアップデートの画像は Peri $ scope ツールで描画されるため、画像は少し異なります。 @
は、@
構文を使用する分離スコーププロパティがあることを示し、ピンクの背景は、ツールがマッピングの祖先参照を見つけることができなかったことを意味します(これは、 tはまだテキストボックスに入力します)。
テキストボックスにmy title
と入力すると、次のようになります。
@
バインディングを使用する分離プロパティは、@
シンボルの後に分離スコープで補間された文字列の結果を常に表示します。また、Peri $ scopeは祖先スコープでこの正確な文字列値を見つけることができたため、そのプロパティへの参照も表示されます。
Fiddle 2では、入力する前に、fiddle1と同じ画像が表示されます。
my title
と入力した後:
新しいdata.title
プロパティが表示された場所に注目してください-トランスクルードされたスコープ上。分離スコープはまだコントローラースコープでdata.title
を探していますが、今回はそこにないため、そのtitle
プロパティ値は空のままです。
Fiddle3では、入力する前にfiddle1と同じ画像が表示されます。
my title
と入力した後:
分離スコープの新しいdata.title
プロパティが表示された場所に注目してください。トランスクルードされたスコープは、$parent
関係を介して分離スコープにアクセスできますが、title
またはdata.title
を検索することはありません。コントローラースコープのみを検索します(つまり、プロトタイプの継承に従います)、コントローラースコープにはこれらのプロパティが定義されていません。
マークの素晴らしい回路図を含む提示されたすべての答えを読んだ後、これは私のスコープの理解であり、私の質問ごとの継承です。適切に更新できるように、この図がどこに落ちるかについてのコメントをいただければ幸いです。マークが提示したものとは異なる見方を提供することを願っています。
よく尋ねました、ところで!私の答えが雄弁であることを願っています。
答えは、トランスクルードされた要素がどのようにスコープを取得するかに関係しています。
要約すると、2つのスコープがあります。
$scope.data.title
を持つコントローラーのスコープ。 (input
要素によって暗黙的に追加されます)$scope.title
を持つディレクティブのスコープ。コントローラの$scope.data.title
を変更すると、ディレクティブの$scope.title
も変更されます。
HTMLの2つのセクション、トランスクルードされたテンプレートとテンプレートもあります。何が起こっているかというと、トランスクルードされたHTMLはcontroller'sスコープにあり、テンプレートHTMLはdirective'sスコープ。したがって、トランスクルードされたHTMLはtitle
について何も知りません。また、テンプレートスコープはdata.title
について何も知りません。
これは実際、トランスクルージョンが意図したとおりです-ディレクティブの子要素が親スコープ、この場合はコントローラーのスコープを保持できるようにするため設計上、トランスクルードされた要素はディレクティブ内にあることを認識しないため、ディレクティブのスコープにアクセスできません。
一方、ディレクティブテンプレートは、ディレクティブのスコープにのみアクセスできます。
名前をもう少し明確にするためにコードを少し変更しました(同じ機能ですが)