Wie funktioniert die Datenbindung im AngularJS
-Framework?
Ich habe keine technischen Details auf ihrer Website gefunden. Es ist mehr oder weniger klar, wie es funktioniert, wenn Daten vom View zum Model propagiert werden. Aber wie verfolgt AngularJS Änderungen von Modelleigenschaften ohne Setter und Getter?
Ich habe herausgefunden, dass es JavaScript watchers gibt, die diese Aufgabe übernehmen können. Aber sie werden in Internet Explorer 6 und Internet Explorer 7 nicht unterstützt. Woher weiß AngularJS also, dass ich z. B. Folgendes geändert und diese Änderung in einer Ansicht wiedergegeben habe?
myobject.myproperty="new value";
AngularJS merkt sich den Wert und vergleicht ihn mit einem früheren Wert. Dies ist eine grundlegende Überprüfung. Wenn sich der Wert ändert, wird das Änderungsereignis ausgelöst.
Die Methode "$apply()", die Sie aufrufen, wenn Sie von einer Nicht-AngularJS-Welt in eine AngularJS-Welt wechseln, ruft "$digest()" auf. Ein Digest ist eine einfache, alte Schmutzprüfung. Er funktioniert auf allen Browsern und ist völlig vorhersehbar.
Gegenüberstellung von Dirty-Checking (AngularJS) und Change Listener (KnockoutJS und Backbone.js): Während Dirty-Checking einfach und sogar ineffizient erscheinen mag (darauf werde ich später eingehen), stellt sich heraus, dass es semantisch immer korrekt ist, während Change-Listener viele seltsame Eckfälle haben und Dinge wie Dependency-Tracking benötigen, um sie semantisch korrekter zu machen. KnockoutJS Dependency Tracking ist ein cleveres Feature für ein Problem, das AngularJS nicht hat.
Es mag also den Anschein haben, dass wir langsam sind, da die Schmutzkontrolle ineffizient ist. Hier müssen wir uns mit realen Zahlen befassen, anstatt nur theoretische Argumente zu haben, aber lassen Sie uns zunächst einige Einschränkungen definieren.
Menschen sind:
Langsam - Alles, was schneller als 50 ms ist, ist für Menschen nicht wahrnehmbar und kann daher als "sofort" betrachtet werden.
Die eigentliche Frage ist also die folgende: Wie viele Vergleiche können Sie mit einem Browser in 50 ms durchführen? Diese Frage ist schwer zu beantworten, da viele Faktoren eine Rolle spielen, aber hier ist ein Testfall: http://jsperf.com/angularjs-digest/6, der 10.000 Watcher erzeugt. Auf einem modernen Browser dauert dies knapp 6 ms. Bei Internet Explorer 8 dauert es etwa 40 ms. Wie Sie sehen, ist dies heutzutage selbst bei langsamen Browsern kein Problem mehr. Es gibt einen Vorbehalt: Die Vergleiche müssen einfach sein, damit sie in das Zeitlimit passen... Leider ist es viel zu einfach, einen langsamen Vergleich in AngularJS einzubauen, so dass es einfach ist, langsame Anwendungen zu erstellen, wenn man nicht weiß, was man tut. Aber wir hoffen, eine Antwort zu haben, indem wir ein Instrumentierungsmodul bereitstellen, das Ihnen zeigen würde, welche Vergleiche langsam sind.
Es hat sich herausgestellt, dass Videospiele und GPUs den Dirty-Checking-Ansatz verwenden, weil er konsistent ist. Solange sie über die Bildwiederholfrequenz des Monitors kommen (typischerweise 50-60 Hz oder alle 16,6-20 ms), ist jede darüber hinausgehende Leistung eine Verschwendung, so dass es besser ist, mehr zu zeichnen, als die FPS zu erhöhen.
Das ist mein Grundverständnis. Es kann durchaus falsch sein!
$digest
geändert haben.In der normalen Entwicklung weist die Datenbindungssyntax im HTML den AngularJS-Compiler an, die Watches für Sie zu erstellen und die Controller-Methoden werden bereits innerhalb von $apply
ausgeführt. Für den Anwendungsentwickler ist das Ganze also transparent.
Ich habe mich das selbst eine Weile gefragt. Wie bemerkt AngularJS
ohne Setter Änderungen am $scope
Objekt? Fragt es sie ab?
Was es tatsächlich tut, ist Folgendes: Jeder "normale" Ort, an dem Sie das Modell ändern, wurde bereits von den Eingeweiden von AngularJS
aufgerufen, also ruft es automatisch $apply
für Sie auf, nachdem Ihr Code läuft. Nehmen wir an, Ihr Controller hat eine Methode, die mit ng-click
auf ein Element verbunden ist. Weil AngularJS
den Aufruf dieser Methode für dich verdrahtet, hat es die Möglichkeit, ein $apply
an der richtigen Stelle auszuführen. Ebenso werden Ausdrücke, die direkt in den Ansichten erscheinen, von AngularJS ausgeführt, so dass es die "$apply" ausführt.
Wenn die Dokumentation davon spricht, dass man $apply
manuell für Code außerhalb von AngularJS
aufrufen muss, dann geht es um Code, der, wenn er ausgeführt wird, nicht von AngularJS
selbst im Aufrufstapel stammt.