Es ist nicht einfach, diese Frage zu formulieren, also werde ich versuchen, mit einem Beispiel zu erklären, was ich wissen möchte:
Betrachten Sie diese einfache angularjs app
: PLUNKER
Mit diesem HTML:
%Vor%Die App:
So weit, so gut.
Nehmen wir nun eine kleine Änderung vor: PLUNKER
%Vor%und das:
%Vor%Das einzige, was wir getan haben, ist:
window.alert
anzeigt, wenn das Attribut 'isChecked' des Bereichs des Controllers aktiviert oder deaktiviert ist. (Ich mache absichtlich einen window.alert
, weil ich möchte, dass die Ausführung aufhört) Wenn wir nun das Kontrollkästchen aktivieren oder deaktivieren, erhalten wir eine Warnung, und in dieser Warnung können wir sehen, dass der Geltungsbereich der Richtlinie noch nicht aktualisiert wurde. Ok, also würde man denken, dass ng-change
ausgelöst wird, bevor das Modell aktualisiert wird. Auch während der Anzeige der Warnung können wir sehen, dass "isChecked" entsprechend dem im Browser gerenderten Text in beiden Bereichen den gleichen Wert hat. Alles klar, keine große Sache, wenn sich die "ng-change" so verhält, können wir immer $watch
setzen und die Funktion dort ausführen ... Aber machen wir noch ein Experiment:
Wie folgt: PLUNKER
%Vor%Jetzt benutzen wir nur eine Funktion des Bereichs der Direktive, um dasselbe zu tun, was die Funktion des Bereichs des Controllers tat, aber dieses Mal stellt sich heraus, dass das Modell aktualisiert wurde, so scheint es An dieser Stelle wird der Geltungsbereich der Richtlinie aktualisiert, aber der Umfang des Controllers wird nicht aktualisiert ... Seltsam!
Stellen wir sicher, dass das der Fall ist: PLUNKER
%Vor% Diesmal benutzen wir die Funktion des Bereichs der Direktive, um die gebundene Funktion des Controllers auszulösen, und wir übergeben ein Argument an die Funktion des Controllers mit dem Wert des Bereichs der Direktive. Nun können wir in der Funktion des Controllers bestätigen, was wir bereits im vorherigen Schritt vermutet haben: Der isolierte Bereich wird zuerst aktualisiert, dann wird ng-change
ausgelöst, und erst danach werden die Bindungen des Bereichs der Direktive ausgelöst aktualisiert.
Nun, endlich, meine Frage / n:
Mit anderen Worten: Wenn "ng-change" ausgelöst wurde, bevor das Modell aktualisiert wird, kann ich das verstehen, aber es fällt mir sehr schwer zu verstehen, dass eine Funktion nach dem Aktualisieren des Modells und vor dem Beenden ausgelöst wird Füllen Sie die Änderungen der gebundenen Eigenschaften.
Wenn Sie so weit lesen: Herzlichen Glückwunsch und vielen Dank für Ihre Geduld!
Josep
Um das Problem zusammenzufassen, muss ngModelController
einen Prozess durchlaufen, bevor watches
ausgelöst wird. Sie protokollieren die äußere Eigenschaft $scope
, bevor ngModelController
die Änderung verarbeitet und einen $ digest-Zyklus verursacht hat, der wiederum $watchers
ausgelöst hat. Ich würde das model
bis zu diesem Punkt nicht berücksichtigen.
Dies ist ein komplexes System. Ich habe diese Demo als Referenz gemacht. Ich empfehle, die return
-Werte zu ändern, zu tippen und zu klicken - einfach auf verschiedene Arten damit herumzuspielen und das Protokoll zu überprüfen. Dadurch wird schnell klar, wie alles funktioniert.
ngModelController
verfügt über eigene Funktionsarrays, die als Antwort auf verschiedene Änderungen ausgeführt werden können.
ngModelController
hat zwei Arten von "Pipelines", um zu bestimmen, was mit einer Art von Änderung zu tun ist. Diese erlauben dem Entwickler, den Fluss von Werten zu steuern.
Wenn sich die als ngModel
zugewiesene Bereichseigenschaft ändert, wird die Pipeline $formatter
ausgeführt. Diese Pipeline wird verwendet, um zu bestimmen, wie der Wert von $scope
in der Ansicht angezeigt werden soll, lässt das Modell jedoch unverändert. Also, ng-model="foo"
und $scope.foo = '123'
, würden normalerweise 123
in der Eingabe anzeigen, aber der Formatierer könnte 1-2-3
oder einen beliebigen Wert zurückgeben. $scope.foo
ist immer noch 123, aber es wird angezeigt, was auch immer der Formatierer zurückgegeben hat.
$parsers
behandelt dasselbe, aber umgekehrt. Wenn der Benutzer etwas eingibt, wird die $ -Parser-Pipeline ausgeführt. Was auch immer $parser
zurückgibt, wird auf ngModel.$modelValue
gesetzt. Wenn der Benutzer also abc
und $parser
a-b-c
zurückgibt, ändert sich die Ansicht nicht, aber $scope.foo
ist jetzt a-b-c
.
Nachdem entweder $formatter
oder $parser
ausgeführt wurde, wird $validators
ausgeführt. Die Gültigkeit des für den Validator verwendeten Eigenschaftsnamens wird durch den Rückgabewert der Validierungsfunktion ( true
oder false
) festgelegt.
$viewChangeListeners
werden nach Ansichtsänderungen ausgelöst, nicht nach Modelländerungen. Dies ist besonders verwirrend, weil wir uns auf $scope.foo
und NOT ngModel.$modelValue
beziehen. Eine Ansicht aktualisiert unweigerlich ngModel.$modelValue
(sofern nicht in der Pipeline verhindert), aber das ist nicht das model change
, auf das wir uns beziehen. Grundsätzlich werden $viewChangeListeners
nach $parsers
und NICHT nach $formatters
ausgelöst. Wenn sich der Ansichtswert ändert (Benutzertypen), wird $parsers, $validators, then $viewChangeListeners
angezeigt. Spaß mal = D
All dies geschieht intern von ngModelController
. Während des Vorgangs wird das ngModel
-Objekt nicht wie erwartet aktualisiert. Die Pipeline gibt Werte weiter, die sich auf dieses Objekt auswirken. Am Ende des Prozesses wird das Objekt ngModel
mit den richtigen $viewValue
und $modelValue
aktualisiert.
Schließlich wird die ngModelController
ausgeführt und ein $digest
Zyklus wird ausgeführt, damit der Rest der Anwendung auf die resultierenden Änderungen reagieren kann.
Hier ist der Code aus der Demo, falls etwas damit passieren sollte:
%Vor%JS:
%Vor%Tags und Links angularjs angularjs-directive angularjs-scope