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?

War es hilfreich?

Lösung

Es gibt drei Mechanismen, die dieses Verhalten erklären:

  1. Die Beobachter werden im hingerichtet die selbe Reihenfolge dass sie registriert sind (siehe den Code des $watch Methode()).

  2. Die Post-Link-Funktionen werden im ausgeführt umgekehrte Reihenfolge ihrer Priorität (siehe Dokumentation dazu priority Eigentum).

  3. 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 der select Richtlinie als auch eine Priorität von 0, 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 als 0.
  • 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.
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top