it-swarm.com.de

Verwirrt über Angularjs abgelegene und isolierte Bereiche und Bindungen

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.

55
dewd

Ihre Geigen schaffen drei Bereiche:

  1. ein Bereich, der dem Controller Ctrl zugeordnet ist, aufgrund von ng-controller
  2. ein durch die Direktive überdeckter Geltungsbereich, wegen transclude: true
  3. ein Direktiven-Isolate-Bereich, wegen scope: { ... }

Bevor wir in fiddle1 etwas in das Textfeld eingeben, haben wir Folgendes:

enter image description here

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:

enter image description here

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:

enter image description here

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:

enter image description here

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:

enter image description here

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:

enter image description here

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:

enter image description here

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:

enter image description here

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.

113
Mark Rajcok

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:

Scope inheritance

22
dewd

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:

  1. Der Bereich des Controllers, der $scope.data.title. (Implizit hinzugefügt von Ihrem input -Element)
  2. Der Geltungsbereich der Richtlinie, der $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)

http://jsfiddle.net/yWWVs/2/

8
Roy Truelove