Ich kämpfe darum, den Anwendungsbereich von Modellen und ihre Bindungen in Bezug auf Richtlinien zu verstehen, die einen begrenzten Anwendungsbereich haben.
Wenn ich den Gültigkeitsbereich einer Direktive einschränke, bedeutet dies, dass controller. $ Scope und direction.scope nicht mehr dasselbe sind. Ich bin jedoch verwirrt darüber, wie sich die Platzierung von Modellen innerhalb der Direktivenvorlage oder im HTML auf die Datenbindung auswirkt. Ich habe das Gefühl, dass mir etwas sehr Grundlegendes fehlt, und um weitermachen zu können, muss ich dies verstehen.
Nimm den folgenden Code (Geige hier: 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>
Das Modell aktualisiert nur {{title}}
innerhalb der Vorlage und {{data.title}}
in der Transklusion. Warum nicht {{title}}
in der Transklusion noch {{data.title}}
in der Vorlage?
Verschieben der Eingabe in die Transklusion wie folgt (hier fummeln: 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>
jetzt heißt nur transclude {{data:title}}
wird aktualisiert. Warum nicht entweder Vorlage {{title}}
oder {{data.title}}
, noch transclude {{title}}
?
Zum Schluss verschieben Sie die Eingabe wie folgt in die Vorlage (hier fummeln: 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>'
Jetzt heißt das nur Vorlage {{data.title}}
wird aktualisiert. Warum nicht die anderen 3 Bindungen?
Ich hoffe, es gibt etwas Offensichtliches, das mich ins Gesicht starrt und ich vermisse es. Wenn Sie mich dazu bringen, kaufe ich Ihnen ein Bier oder gebe Ihnen Punkte oder ähnliches. Danke vielmals.
Ihre Geigen schaffen drei Bereiche:
Ctrl
zugeordnet ist, aufgrund von ng-controller
transclude: true
scope: { ... }
Bevor wir in fiddle1 etwas in das Textfeld eingeben, haben wir Folgendes:
Bereich 003 ist der dem Controller zugeordnete Bereich. Da wir noch nichts in das Textfeld eingegeben haben, gibt es keine data
-Eigenschaft. Im isolierten Bereich 004 sehen wir, dass eine title
-Eigenschaft erstellt wurde, diese jedoch leer ist. Es ist leer, da der übergeordnete Bereich noch keine data.title
- Eigenschaft hat.
Nach der Eingabe von my title
In das Textfeld haben wir jetzt:
Der Controller-Bereich 003 verfügt jetzt über eine neue Objekteigenschaft data
(weshalb sie gelb gefärbt ist), für die die Eigenschaft title
jetzt auf my title
Festgelegt ist. Da die Isolate-Scope-Eigenschaft title
eine Einwegdatenbasis zum interpolierten Wert von data.title
Ist, erhält sie auch den Wert my title
(Der Wert wird gelb gefärbt, weil er sich geändert hat).
Der übermittelte Gültigkeitsbereich erbt prototypisch vom Controller-Gültigkeitsbereich, sodass im übermittelten HTML-Code angular) der Prototypenkette folgen und $scope.data.title
Im übergeordneten Gültigkeitsbereich finden kann (aber $scope.title
existiert dort nicht).
Der Isolatbereich hat nur Zugriff auf seine eigenen Eigenschaften, daher nur die Eigenschaft title
.
In fiddle2 haben wir vor dem Tippen das gleiche Bild wie in fiddle1.
Nach der Eingabe von my title
:
Beachten Sie, wo die neue data.title
- Eigenschaft im übermittelten Bereich angezeigt wurde. Der Isolate-Bereich sucht immer noch nach data.title
Im Controller-Bereich, ist diesmal jedoch nicht vorhanden, sodass sein Eigenschaftswert title
leer bleibt.
In fiddle3 haben wir vor dem Tippen das gleiche Bild wie in fiddle1.
Nach der Eingabe von my title
:
Beachten Sie, wo die neue Eigenschaft data.title
Auf dem Isolatbereich angezeigt wurde. Keiner der anderen Bereiche hat Zugriff auf den Isolationsbereich, daher wird die Zeichenfolge my title
Nirgendwo anders angezeigt.
Update für Angular v1.2:
Mit change eed299a Angular löscht jetzt den Transklusionspunkt vor dem Transkludieren, sodass die Teile Template title: ...
Und Template data.title: ...
Nur angezeigt werden, wenn Sie ändern die Vorlage so, dass ng-transclude
für sich alleine ist, wie zum Beispiel:
'<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>'
Im folgenden Update für Angular v1.3 wurde diese Vorlagenänderung vorgenommen.
Update für Angular v1.3 +:
Seit Angular v1.3 ist der übermittelte Bereich nun ein untergeordnetes Element des Isolate-Bereichs der Direktive und kein untergeordnetes Element des Controller-Bereichs. Geben Sie also in fiddle1 Folgendes ein, bevor Sie etwas eingeben:
Die Bilder in diesem Update werden mit dem Werkzeug Peri $ scope gezeichnet, daher sind die Bilder etwas anders. Das @
Zeigt an, dass wir eine Isolate-Scope-Eigenschaft haben, die die @
- Syntax verwendet, und der rosa Hintergrund bedeutet, dass das Tool keine Vorfahrenreferenz für die Zuordnung finden konnte (was seitdem zutrifft) habe noch nichts in das Textfeld eingegeben).
Nach der Eingabe von my title
In das Textfeld haben wir jetzt:
Isolateigenschaften, die die Bindung @
Verwenden, zeigen immer das Ergebnis der interpolierten Zeichenfolge im Isolationsbereich nach dem Symbol @
An. Peri $ scope konnte diesen exakten Zeichenfolgenwert auch in einem Vorgängerbereich finden, sodass auch ein Verweis auf diese Eigenschaft angezeigt wird.
In Fiddle 2 haben wir vor dem Tippen das gleiche Bild wie in Fiddle1.
Nach der Eingabe von my title
:
Beachten Sie, wo die neue data.title
- Eigenschaft im übermittelten Bereich angezeigt wurde. Der Isolate-Bereich sucht immer noch nach data.title
Im Controller-Bereich, ist diesmal jedoch nicht vorhanden, sodass sein Eigenschaftswert title
leer bleibt.
In fiddle3 haben wir vor dem Tippen das gleiche Bild wie in fiddle1.
Nach der Eingabe von my title
:
Beachten Sie, wo die neue Eigenschaft data.title
Auf dem Isolatbereich angezeigt wurde. Obwohl der übermittelte Bereich über die Beziehung $parent
Zugriff auf den isolierten Bereich hat, sucht er dort nicht nach title
oder data.title
- er sucht nur im Controller scope (dh es folgt der prototypischen Vererbung), und im Bereich des Controllers sind diese Eigenschaften nicht definiert.
Nachdem ich alle Antworten gelesen habe, einschließlich Marks fantastischer Schaltpläne, ist dies mein Verständnis des Umfangs und seiner Vererbung gemäß meiner Frage. Ich würde mich über Kommentare darüber freuen, wo dieses Diagramm herunterfällt, damit ich es entsprechend aktualisieren kann. Ich hoffe, es bietet einfach eine andere Sicht auf das, was Mark präsentiert hat:
Gut gefragt, übrigens! Hoffe, meine Antwort ist so beredt ..
Die Antwort hat damit zu tun, wie vertrauliche Elemente ihren Geltungsbereich erhalten.
Zusammenfassend haben Sie zwei Bereiche:
$scope.data.title
. (Implizit hinzugefügt von Ihrem input
-Element)$scope.title
.Wenn Sie den Regler wechseln, wird $scope.data.title
, Direktive $scope.title
ändert sich auch.
Sie haben auch zwei Abschnitte von HTML, die transkludierte und die Vorlage. Was passiert, ist, dass der übertragene HTML-Code im Bereich controller's und der Vorlagen-HTML-Code im Bereich direct's liegt. Der transkludierte HTML-Code weiß also nichts über title
, und der Vorlagenbereich weiß nichts über data.title
Dies ist eigentlich genau das, wofür Transclusion gedacht war - um zuzulassen, dass untergeordnete Elemente einer Direktive ihren übergeordneten Gültigkeitsbereich behalten, in diesem Fall den Gültigkeitsbereich des Controllers. Übertragene Elemente wissen von Natur aus nicht, dass sie sich in einer Direktive befinden, und haben daher keinen Zugriff auf den Geltungsbereich der Direktive.
Auf der anderen Seite haben Richtlinienvorlagen nur Zugriff auf den Geltungsbereich der Richtlinie.
Ich habe deinen Code ein wenig geändert, um die Namen ein bisschen klarer zu machen (gleiche Funktionalität)