Möchten Sie eine Funktion anfordern oder einen Fehler melden?
Ich weiß nicht ob es gewollt ist oder ob es ein Bug ist
Wie ist das aktuelle Verhalten?
Der erste $onChanges
Aufruf wird vor dem $onInit
Aufruf ausgeführt.
Bei der Standardkonfiguration von Angular 1.6 (preassign = false) ist es vorzuziehen, Controller-Zustände in der $onInit
Funktion zu initialisieren, da die Bindungen im Konstruktor noch nicht zugänglich sind.
Was ist das erwartete Verhalten?
Ich denke, es wäre logischer, zuerst $onInit
anzurufen.
Angular sollte nichts tun, solange der Controller nicht vollständig initialisiert ist.
Was ist die Motivation / der Anwendungsfall für die Verhaltensänderung?
Wenn wir Objekte verwenden, die in der Funktion $onInit
erstellt werden sollen, in der Funktion $onChanges
; Wir werden beim ersten Aufruf einen Fehler haben, da der Controller noch nicht initialisiert wurde.
Eine Lösung könnte darin bestehen, diese Objekte innerhalb des Konstruktors zu initialisieren, aber wir werden den Controller an zwei verschiedenen Stellen initialisieren ...
Welche Angular-Versionen und welche Browser/Betriebssysteme sind von diesem Problem betroffen? Bitte testen Sie auch mit den neuesten Stable- und Snapshot-Versionen (https://code.angularjs.org/snapshot/).
eckige 1.6-Version
Dies ist beabsichtigt (hauptsächlich um dem Verhalten von Angular 2+ zu entsprechen). Falls Sie es verpasst haben, können Sie überprüfen, ob es der erste Aufruf (vor $onInit) von $onChanges
, indem Sie den Rückgabewert der Methode isFirstChange()
einer der SimpleChange
Objekte:
{
...
bindings: {foo: '<'},
controller: function SomeController() {
this.$onChanges = function(changes) {
if (changes.foo.isFirstChange()) {
// `$onInit()` has not been called yet...
}
};
}
}
Ich gebe zu, dass meine erste Reaktion die gleiche war. Aus der Perspektive eines mentalen Modells ist es einfacher zu denken, dass $onInit()
das erste ist, was im Controller passiert; dann $onChanges()
, $onChanges()
, $onChanges()
und schließlich $onDestroy()
.
Aber wenn Sie darüber nachdenken, müssen die Bindungen ausgewertet und der Controller-Instanz zugewiesen werden, bevor $onInit
. Dabei wird eine Änderung der (bisher undefinierten) Werte erkannt, die wiederum über $onChanges
gemeldet werden muss.
Schließen, da dies wie erwartet (oder zumindest wie beabsichtigt :wink:) funktioniert.
Vielen Dank für deine Antwort, jetzt ist es klarer :)
Ich verstehe, dass dies beabsichtigt ist, wie wäre es, wenn wir die Definition der Funktion $onChanges() in $onInit() registrieren.
@bharatpatil , es sollte in AngularJS (1.x.)
if (changes.foo.isFirstChange()) {
//$onInit()
wurde noch nicht aufgerufen...
}
@gkalpak Ich denke, dieses Argument ist falsch. binding.isFirstChange()
Methode garantiert nur, dass die zugehörige Bindung zum ersten Mal aufgerufen wurde. Denken Sie an eine Bindung, die initialisiert wird, nachdem ein Serviceaufruf zu lange dauert. In dieser Situation sollte die Methode controller.$onInit
Methode controller.$onChanges
aufgerufen werden. Liege ich falsch?
Eine Bindung hat am Anfang immer einen Wert (kann undefined
), der sich immer von ihrem vorinitialisierten Wert unterscheidet. Daher wird $onChanges()
immer mit changes.foo
aufgerufen, bevor $onInit()
aufgerufen wird.
Es macht keinen logischen Sinn, dass eine Bindung einen Wert haben kann, bevor sie initialisiert wurde. Das ist die Wörterbuchdefinition des Wortes initialisieren (Anfangswerte setzen). Sie können etwas nicht ändern, wenn es keinen Anfangswert hat. Ich denke, die Namensgebung ist hier ganz falsch und unnatürlich.
Ich kann mich an keine Situation erinnern, in der ich nicht gezwungen war, so etwas wie diesen Code zu schreiben:
$onChanges(changesObj: { [index: string]: angular.IChangesObject; }) {
if (!this.isInitialized) return;
...
}
"Änderungen" vor "Initialisierung" aufzurufen macht keinen Sinn.
Standardmäßig mit Angular ... warum sollte jemand erwarten, dass init vor Änderungen stattfindet?
Hilfreichster Kommentar
Dies ist beabsichtigt (hauptsächlich um dem Verhalten von Angular 2+ zu entsprechen). Falls Sie es verpasst haben, können Sie überprüfen, ob es der erste Aufruf (vor $onInit) von
$onChanges
, indem Sie den Rückgabewert der MethodeisFirstChange()
einer derSimpleChange
Objekte:#
Ich gebe zu, dass meine erste Reaktion die gleiche war. Aus der Perspektive eines mentalen Modells ist es einfacher zu denken, dass
$onInit()
das erste ist, was im Controller passiert; dann$onChanges()
,$onChanges()
,$onChanges()
und schließlich$onDestroy()
.Aber wenn Sie darüber nachdenken, müssen die Bindungen ausgewertet und der Controller-Instanz zugewiesen werden, bevor
$onInit
. Dabei wird eine Änderung der (bisher undefinierten) Werte erkannt, die wiederum über$onChanges
gemeldet werden muss.Schließen, da dies wie erwartet (oder zumindest wie beabsichtigt :wink:) funktioniert.