2013-05-22 11 views
16

Ich benutze den Router (war mit dem eingebauten, jetzt mit ui-Route aber Lösungen für beide sind in Ordnung) in Angular.JS, um zwischen Steuerelement/Vorlage-Paare zu wechseln. Wenn man zwischen ein paar dieser Seiten hin- und herwechselt, dauert es bis zu einer Sekunde, um das DOM jedes Mal einzurichten, was schrecklich aussieht. Gibt es überhaupt einen eckigen Halt um den DOM-Baum, anstatt ihn jedes Mal neu zu erstellen. Ich denke, ich möchte die Bits für jede Seite einfach verstecken/säen, anstatt sie jedes Mal zu entfernen/neu zu erstellen.Cache-DOM in Angular.JS

Alle Vorschläge willkommen!

+2

Sie können Bereiche mit [ng-show] (http://docs.angularjs.org/api/ng.directive:ngShow) ein-/ausblenden. Vielleicht möchten Sie auch in [$ templateCache] (http://docs.angularjs.org/api/ng.$templateCache) schauen, mit dem Sie Ihre Ansichten zwischenspeichern können. –

+0

Ich denke, ich könnte uns ng-zeigen, aber dann müsste ich nicht das Loch Router und URL Management wegwerfen, dass Angular bietet? Nicht sicher, wie Sie $ templateCache verwenden, kann ich Dinge einrichten, so dass alle Vorlagen zwischengespeichert werden? –

+0

Sie könnten zwei ng-app verwenden, um zwei Verhaltensweisen zu verwalten, denke ich. – GnrlBzik

Antwort

4

Sie müssen Ihre eigene ng-view-Direktive schreiben, um solche Funktionalität zu erstellen.

Die grundlegende Idee dahinter ist:

Bevor die Route ändert, anstatt die aktuelle Ansicht Element zu zerstören, und den Umfang, können Sie es nur in einem unsichtbaren Cache DIV gesetzt und Umfang Hörer deregistrieren. Geben Sie dem Element ein Datenattribut mit der $$route.templateUrl, um es zurückbekommen zu können. Dann holen Sie die nächste Ansicht vom Server.

Bevor Sie die Route ändern, prüfen Sie, ob der Cache-Eintrag vorhanden ist. Wenn er in Ihrem Cache div das Element aus dem Cache abruft, listen Sie Listener erneut auf und setzen Sie den Cache in die aktuelle Ansicht.

Der schwierige Teil ist nicht, die $scope s zu stören. Also brauchen Sie vielleicht einen Konstruktor und einen Destruktor in Ihrem $scope für das Event und vielleicht auch für die $ watchers. Ich bin mir nicht sicher.

Aber um ehrlich zu sein, wenn Sie den Vorlagen-Cache verwenden und noch 1 Sekunde oder so zu rendern, dann haben Sie möglicherweise einige ineffiziente $watch Ausdruck oder eine große ng-repeat. Sie sollten etwas Refact in Betracht ziehen.

+1

+1 für die Performance-Kommentar im letzten Absatz – w00t

+0

Ist es wirklich jemand auf ein echtes Problem hilft? Wenn jemand ein Beispiel gibt, wie es mit Code funktioniert, wird es großartig. – alexche8

0

Wenn Sie zu Angular 1.1.5 wechseln, können Sie das ng-animate-Attribut für Ihr ng-view-Tag verwenden.

Ich bin nicht 100% sicher, aber ich denke, dass es einige DOM-Caching tut, um die Übergänge besser arbeiten zu lassen. Sie könnten versuchen, das ng-animate-Attribut zum Tag hinzuzufügen. Das könnte sich darum kümmern.

2

Ich habe das selbst erforscht. Ich arbeite an ziemlich alter Hardware in einem unbeschleunigten Browser. Der erste Rendervorgang ist ein Problem. Meine frühe Arbeit war, vorkompilierte Vorlagen zu cachen, wie Sie versuchen. Ich fand, dass dies nur eine minimale Geschwindigkeitsverbesserung lieferte.

Der eigentliche Engpass kam von meinen ng-repeat-Direktiven, der Anzahl der resultierenden Reflows und der Anzahl der DOM-Knoten/Wächter, die ich in jeder Iteration baute.

Einige Quellen haben vorgeschlagen, eine benutzerdefinierte Direktive zu erstellen, die das dom manuell zusammenfügt und es auf einmal anfügt. Das Ergebnis ist ein sehr minimaler Reflow und keine Beobachter. Der Nachteil ist sehr groß. Kein winkeliger Spaß mehr und viel unnötige Arbeit. Wichtiger noch, nichts davon lieferte eine ausreichend große Geschwindigkeitsverbesserung, um die Arbeit zu rechtfertigen.

Ich fand schließlich, dass die beste Geschwindigkeitsverbesserung vom Erzwingen der Hardwarebeschleunigung für jede ng-Wiederholungsiteration kam. Wie oben angedeutet, macht die ng-animate-Direktive in neueren Versionen eckig dies relativ trivial.

Sie werden die sofortige Seitenwiedergabe mit kleinen Reflow-Schluckauf sehen. ng-Umhang hilft hier nicht. Aufgrund der Animationsanforderung ist die Seite nicht getarnt, während die Wiederholung gerendert wird.Diese können jedoch mit etwas cleverem Spaß einigermaßen gut wiedergegeben werden. Ich verstecke eigentlich die ng-Wiederholung, bis der $ Standort sich ändert, eine Fortschrittsanzeige in der Zwischenzeit zeigend, und dann meine ng-Show umschalte. Das funktioniert wirklich gut.

Nachdem all das gesagt wurde, sollten Sie Ihre Vorlagen vorkompilieren wie folgt.

1) Wenn Ihre App startet, erstellen Sie einen neuen Cache für sich. Siehe http://docs-angularjs-org-dev.appspot.com/api/ng. $ CacheFactory

2) Füllen Sie diesen Cache mit kompiliert Vorlagen. Inject $ compile und rufen Sie es für jede Vorlage auf. Kompilieren gibt eine Funktion zurück, die Sie später für Ihren Bereich aufrufen werden. Geben Sie diese Funktion in Ihren Cache ein, so wie Sie es für richtig halten.

3) Erstellen Sie eine benutzerdefinierte Anweisung, die einen Cache-Schlüssel als Attribut akzeptiert. Suchen Sie in dieser Anweisung Ihren Kompiliercache nach der richtigen Kompilierfunktion ab. Rufen Sie die Funktion für Ihren aktuellen Bereich auf und hängen Sie das resultierende DOM an das Element an, das an die Anweisung übergeben wurde.

4) Sorta gewinnen :).

+0

Kannst du mir helfen, Teil 3 zu machen? Frage deinen Kompilier-Cache nach der richtigen Kompilierfunktion ab? – Salman

+1

Gibt es ein Live-Beispiel für diese Methode? Es gibt Unmengen von Dingen, die hier versteckt sind: – yccteam