Warum verwenden die AngularJS-Dokumente keinen Punkt in der Modellanweisung?


70

In dem Video AngularJS MTV Meetup: Best Practices (2012/12/11) erklärt Miško: "..wenn Sie das ng-Modell verwenden, muss irgendwo ein Punkt sein. Wenn Sie keinen Punkt haben, tun Sie es falsch.."

Das allererste Beispiel (The Basics) auf der Angular.JS-Website scheint dem jedoch zu widersprechen. Was gibt? Hat sich Angular.JS seit dem MTV-Treffen geändert, dass es jetzt mit ng-model verzeihender ist?


Ich persönlich denke, dies ist eher ein philosophisches Problem bei der Modellierung eines Systems. Einige Leute verwenden $scopeals Ansichtsmodell, andere nicht. Es ist eine Frage der Präferenz.
Yuxhuang

Antworten:


109

Dieser kleine Punkt ist sehr wichtig, wenn es um die Komplexität der Bereichsvererbung geht.

Das egghead.io-Video "The Dot" hat einen wirklich guten Überblick, ebenso wie diese sehr beliebte Frage zum Stapelüberlauf: Was sind die Nuancen der prototypischen / prototypischen Vererbung des Bereichs in AngularJS?

Ich werde versuchen, es hier zusammenzufassen:

Angular.js verwendet die Bereichserbung, damit ein untergeordneter Bereich (z. B. ein untergeordneter Controller) die Eigenschaften des übergeordneten Bereichs anzeigen kann. Nehmen wir also an, Sie hatten ein Setup wie:

<div ng-controller="ParentCtrl">
    <input type="text" ng-model="foo"/>
    <div ng-controller="ChildCtrl">
        <input type="text" ng-model="foo"/>
    </div>
</div>

( Spielen Sie auf einer JSFiddle mit )

Wenn Sie die App gestartet und in die übergeordnete Eingabe eingegeben haben, wird das untergeordnete Element zunächst aktualisiert, um es wiederzugeben.

Wenn Sie jedoch den untergeordneten Bereich bearbeiten, wird die Verbindung zum übergeordneten Bereich jetzt unterbrochen und die beiden werden nicht mehr synchronisiert. Wenn Sie dagegen verwenden ng-model="baz.bar", bleibt der Link erhalten.

Der Grund dafür ist, dass der untergeordnete Bereich eine prototypische Vererbung verwendet, um den Wert nachzuschlagen. Solange er nicht für das untergeordnete Element festgelegt wird, wird er auf den übergeordneten Bereich verschoben. Sobald es eingestellt ist, sucht es nicht mehr nach dem Elternteil.

Wenn Sie bazstattdessen ein Objekt ( ) verwenden, wird für den untergeordneten Bereich nie etwas festgelegt, und die Vererbung bleibt erhalten.

Weitere Informationen finden Sie in der StackOverflow-Antwort


3
Dieses Egghead-Video ist Gold wert. Beste Beschreibung dieses Problems überhaupt.
Ben Barreth

Was für eine prägnante Zusammenfassung - fantastisch.
drjimmie1976

1
Bin ich der einzige, der das Hinzufügen beliebiger Containervariablen für unglaublich hässlich hält? Ich verstehe, warum es eine "Best Practice" ist, aber es ist so hässlich, Zufallsvariablen zu sehen, die das enthalten, was wirklich wichtig ist. Aus diesem Grund vermeide ich diese "Best Practice". Ich stoße nicht oft auf Probleme, weil ich mir der Konsequenzen bewusst bin. Ich bin seit über einem Jahr intensiver Winkelentwicklung nicht mehr davon gebissen worden.
Spencer

@Spencer Meine Faustregel lautet: Wenn es sich nur um eine Benutzeroberfläche handelt (z. B. einen Sichtbarkeitsstatus, der nicht von einem Controller oder Dienst abhängt), verwende ich eine Bereichsvariable der obersten Ebene. Ansonsten lebt alles auf einem Controller (mit controllerAsund bindToControllerSyntax) oder auf einem Dienst, der den Punkt erzwingt.
OverZealous

17

Ein Punkt wird benötigt, wenn Sie einen Bereich prototypisch von einem anderen erben. Beispielsweise wird bei ng-repeat für jede Werbebuchung, die prototypisch vom übergeordneten Bereich erbt, ein neuer Bereich erstellt. Im Basisbeispiel gibt es keine Prototypvererbung, da es nur einen Bereich gibt. Wenn Sie jedoch mehrere untergeordnete Bereiche haben, werden Sie mit dem Problem konfrontiert. Der Link unten macht alles klar.

https://github.com/angular/angular.js/wiki/Understanding-Scopes#ng-repeat


0

Um dies zu lösen, stellen Sie sicher, dass Sie im JS zuerst das übergeordnete Element deklarieren:

z.B

$scope.parent

gefolgt von:

$scope.parent.child = "Imma child";

Wenn Sie nur das Kind ohne die Eltern tun, wird Angular zerstört.


0

Laut der Antwort von @OverZealous habe ich mir dafür eine schmutzige, aber bequem einfache und schnelle Problemumgehung ausgedacht:

$scope.$s = $scope
$scope.foo = 'hello'

Dann kann die Verwendung $sin der Vorlage das Modell sicher ändern:

<input ng-model="$s.foo"/>

Ich habe in meinem Projekt einen Dienst für solche Drecksarbeiten geschrieben.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.