Gültige Direktivennamen
-
21-12-2019 - |
Frage
Ich habe ein ganz spezielles Problem mit einer Direktive, die mit bestimmten Buchstaben beginnt (t, u, v, w, y, z).Die Direktive wird auf a verwendet select
Element und sucht nach ngOptions
Änderungen.
Wann ngOptions
wird mit Daten aus einer Ajax-Anfrage gefüllt und der Direktivenname beginnt mit einem bestimmten Buchstaben, z. B.w, der zweite Watch-Callback wird ausgelöst, bevor die Auswahloptionen erstellt wurden.Wenn der Direktivenname mit einem anderen Buchstaben beginnt (a, k, m, n), wird der zweite Watch-Callback ausgelöst, nachdem die Optionen erstellt wurden.
Hier ist ein Beispiel mit mehreren Anweisungen, die mit verschiedenen Buchstaben beginnen.Öffnen Sie Ihre Konsole, um das Problem zu sehen.
<select w-foo ng-model="bar" ng-options="o.name for o in options"></select>
app.controller("test", function ($scope, $timeout) {
// Emulate ajaxed options
$timeout(function () {
$scope.options = [{
name: "aaa",
id: 1
}, {
name: "bbb",
id: 2
}, {
name: "ccc",
id: 3
}];
}, 500);
});
app.directive("wFoo", function () {
return {
require: 'ngModel',
link: function (scope, element, attrs, ngModel) {
scope.$watch(attrs.ngOptions.replace(/.*in /, ""), function () {
console.log("w-foo ngOptions changed", element.html());
});
}
};
});
Im obigen Code, element.html()
wird ein einzelnes Leerzeichen enthalten option
im ersten Watch-Callback (dem anfänglichen Digest) und enthält auch ein einzelnes Leerzeichen option
im zweiten Digest (wenn der Ajax abgeschlossen ist).
Woher kommt dieses Verhalten?
Lösung
Es gibt drei Mechanismen, die dieses Verhalten erklären:
Die Beobachter werden im hingerichtet die selbe Reihenfolge dass sie registriert sind (siehe den Code des
$watch
Methode()).Die Post-Link-Funktionen werden im ausgeführt umgekehrte Reihenfolge ihrer Priorität (siehe Dokumentation dazu
priority
Eigentum).Anweisungen mit derselben Priorität werden in einer undefinierten Reihenfolge ausgeführt.Die Standardpriorität ist
0
, daher haben alle Ihre benutzerdefinierten Anweisungen hier diese Priorität.Seit derselect
Richtlinie als auch eine Priorität von0
, die Reihenfolge der Ausführung ist undefiniert.Wie Sie bemerken, ist „undefiniert“ etwas übertrieben, und tatsächlich ist die Reihenfolge der Ausführung die alphabetischer Reihenfolge (siehe die
$compile
Code):Direktiven mit einem Namen am Anfang des Wörterbuchs haben eine höhere Priorität.Aber meiner bescheidenen Meinung nach, da dies in der Dokumentation nicht ausdrücklich erwähnt wird, Auf dieses Verhalten kann man sich nicht verlassen.
Zusammenfassend finden Sie hier einige Anwendungsfälle.Jede Direktive registriert einen Beobachter.
Name | Priority | Watcher order
--------+------------+--------------
A | 100 | 3rd
B | 0 | 2nd
C | none (= 0) | 1st
Daher ist es einfach, das Problem zu beheben:
- Wenn Sie den Watcher Ihrer benutzerdefinierten Anweisungen ausführen möchten nach Die
select
Erstens geben Sie Ihrer Direktive einfach eine höhere Priorität als0
. - Wenn Sie den Watcher Ihrer benutzerdefinierten Anweisungen ausführen möchten Vor Die
select
Eins, nun ja ... da negative Priorität verboten ist, können Sie das nicht zuverlässig tun.