Mise en cache de la vue URL / état avec les paramètres

Je fais une application mobile en utilisant Cordova et AngularJS. Actuellement, j'ai installé ui-router pour le routage, mais je suis ouvert à toute autre alternative pour le routage.

Mon désir: je souhaite mettre en cache certaines vues liées aux paramètres. En d'autres termes, je souhaite mettre en cache des chemins (ou des pages).

Exemple de situation: disons que nous voyons une page de tableau de bord, cliquez sur une couverture de livre qui redirige vers le book/2 route book/2 . Ce chemin est chargé pour la première fois dans l'application. Le routeur redirige de BooksController vers BooksController (quel que soit le nom). Maintenant, BooksController charge les données pour $stateParams (book id = 2) et crée une vue remplie d'informations sur le livre choisi.

Ce que je veux dans cette situation:

  1. Je retourne à la page du tableau de bord – il est déjà chargé (mis en cache?)
  2. Je choisis encore le livre n ° 2
  3. Le contrôleur ou le routeur remarque que les données sur ce livre sont déjà chargées
  4. La vue n'est pas recréée, mais elle est extraite du cache

En fait, il serait préférable de mettre en cache tout ce que je visite en fonction du chemin. Le préchargement serait aussi cool.

Raison: performance. Lorsque j'ouvre une liste de livres, je souhaite que cela s'affiche rapidement. Lorsque la vue est créée à chaque fois, l'animation du changement de page semble horrible (ce n'est pas lisse).

Toute aide serait appréciée.

MODIFIER:

Tout d'abord, car je crois que c'est un problème commun pour de nombreux programmeurs d'applications HTML mobiles, j'aimerais préciser certaines informations:

  1. Je ne cherche pas de hacks, mais une solution claire si possible.
  2. Les données dans les vues utilisent AngularJS, donc OUI, il y a des choses comme ng-bind , ng-repeat et ainsi de suite.
  3. La mise en cache est nécessaire pour les données et les éléments DOM . Pour autant que je sache, l'opération de mise en page du navigateur n'est pas aussi coûteuse que de recréer un arbre DOM complet. Et repaint n'est pas ce que nous pouvons omettre.
  4. Avoir des contrôleurs distincts est une chose naturelle. Puisque je pourrais partir sans ça, je ne peux pas imaginer comment cela fonctionnerait de toute façon.

J'ai des semi-solutions mais je vais être sévère à propos de mes envies.

Solution 1.

Placez toutes les vues dans un fichier (je peux le faire en utilisant gulp builder) et utilisez ng-show . C'est la solution la plus simple et je ne crois pas que quelqu'un sachant que AngularJS n'y réfléchit pas.

Un bon tour (à partir de @DmitriZaitsev) consiste à créer une fonction d'aide pour afficher / masquer l'élément en fonction du chemin de localisation actuel.

Avantages:

  1. C'est facile.
  2. CLASSE de la fonction de précharge.

Désavantages:

  1. Toutes les vues doivent être dans un seul fichier. Ne demandez pas pourquoi ce n'est pas pratique.
  2. Comme il s'agit de périphériques mobiles, parfois j'aimerais "effacer" la mémoire. La seule façon dont je peux penser est de supprimer ces enfants de DOM. Sale mais ok.
  3. Je ne peux pas facilement mettre en cache / book / 2 et / book / 3 en même temps. Je devrais créer dynamiquement des enfants DOM sur certains modèles pour chaque vue liée aux paramètres.

Solution 2.

Utilisez Sticky States AND Future States de ui-router-extras qui est génial.

Avantages:

  1. Vue séparée.
  2. Utilisation très claire, très simple, car ce n'est qu'un plugin pour ui-router .
  3. Peut créer des sous-résultats dynamiques. Donc, il serait possible de mettre en cache le book1 , le book2 mais je ne suis pas sûr de book/1 et de book/2

Désavantages:

  1. Encore une fois, je ne suis pas sûr, mais je n'ai pas trouvé d'exemple avec la mise en cache d'une paire / tuple (view, parameters) . À part ça, ça a l'air cool.

C'est précisément le problème que j'ai dû résoudre pour mon site 33hotels.com . Vous pouvez le vérifier et jouer avec les onglets "Filtre" et "Liste des filtres" (correspondant à différentes routes) et voir que la vue est mise à jour instantanément sans délai!

Comment l'ai-je fait? L'idée est étonnamment simple: débarrassez-vous du routeur!

Pourquoi? Parce que la façon dont le routeur fonctionne, c'est qu'il re-compile la vue sur chaque changement de route . Oui, Angular cache le modèle mais pas la vue compilée remplie de données. Même si les données ne changent pas! En conséquence, lorsque j'ai utilisé le routeur dans le passé, le commutateur s'est toujours senti lent et non réactif. Chaque fois que je pouvais remarquer un retard gênant, c'était une fraction de seconde mais encore perceptible.

Maintenant, la solution que j'ai utilisée? Ne compilez pas vos vues! Gardez-les à l'intérieur de votre DOM en tout temps! Ensuite, utilisez ng-hide / ng-show pour les cacher / afficher en fonction des itinéraires:

 <div ng-show="routeIs('/dashboard')"> <-- Your template for Dashboard --> </div> <div ng-show="routeIs('/book')"> <-- Your template for Book --> </div> 

Ensuite, créez une routeIs(string) fonction routeIs(string) dans votre Controller pour tester si $location.path() correspond à la string ou commence par la string si je l'utilise. De cette façon, j'obtiens toujours ma vue pour tous les chemins comme /book/2 . Voici la fonction que j'utilise:

 $scope.routeBegins = function () { return _.some(arguments, function (string) { return 0 === $location.path().indexOf(string); }); }; 

Donc, pas besoin d'être intelligent avec la mise en cache – il suffit de le garder dans le DOM. Cela cachera vos vues pour vous!

Et la meilleure partie est – chaque fois que vos données sont modifiées, Angular mettra à jour instantanément toutes les vues à l'intérieur de votre DOM, même les cachées!

Pourquoi est-ce génial? Parce que, en tant qu'utilisateur, je n'ai pas à attendre l'analyse et la compilation pour le moment où je veux voir le résultat. Je veux cliquer sur l'onglet et voir mes résultats immédiatement! Pourquoi le site devrait-il attendre que je clique dessus, puis commencez tout le re-compilation comme j'attends? Surtout quand cela pourrait être fait facilement avant, pendant le temps où mon ordinateur est inactif.

Y at-il des inconvénients? Le seul réel que je puisse penser est de charger de la mémoire avec plus d'éléments DOM. Cependant, cette taille d'octet réel de mes vues est négligeable, en comparant par exemple avec tous les JS, CSS et les images.

Un autre inconvénient possible mais évitable est le coût de ré-compilation des vues cachées. C'est là que vous pouvez être intelligent et éviter les calculs – les pièces lourdes selon les itinéraires actuels. En outre, vous ne compilez pas la vue entière, juste les parties affectées par les changements de données, ce qui réduit également le coût de calcul.

Je trouve tout à fait remarquable que tout le monde utilise Routes et semble totalement inconscient (ou ignorant) de ce problème.

1) À propos des pages statiques dans l'application (vues), angulaire prend soin de les charger.

Par exemple: pour votre page de tableau de bord, vous ne devez pas vous soucier de la mise en cache de la page, car angulaire prendra soin de cette. Angular ne charge que la vue du tableau de bord une seule fois et toutes les demandes suivantes pour la vue du tableau de bord, angulaire vous montrera simplement la vue (ne pas charger le fichier pour la vue), si elle est une vue statique sans aucune donnée chargée par les appels ajax.

2) si votre tableau de bord est lui-même en train de charger la liste des livres (ou des données similaires) via ajax, vous pouvez indiquer à votre contrôleur de ne charger que les données une fois et de l'enregistrer dans localstorage et sur les demandes ultérieures vers le tableau de bord, Le stockage local.

3) une approche similaire peut être utilisée lorsque votre BooksController charge les données dans une vue. Vous pouvez vérifier dans votre BooksController si la demande pour un livre particulier a déjà été faite et si vous ne pouvez pas la stocker dans localstorage ou la base de données. Et si les données étaient préalablement demandées, vous pouvez charger les mêmes données de la mémoire sans faire de requête au serveur.

Exemple de situation:

Dire que l'utilisateur demande la réservation1, alors

  1. Votre contrôleur, c'est-à-dire BooksController, vérifie si les mêmes données ont été demandées avant,
  2. Sinon, vous pouvez charger les données via l'appel ajax du serveur et également l'enregistrer dans un stockage local.
  3. Si elle a été chargée avant de charger les données stockées dans le stockage local ou dans la base de données.

Si vous utilisez ui.router, vous devriez jeter un oeil à ui.router extras, en particulier le module d'états collant. Cela vous permet de mettre en cache l'arborescence de l'état (y compris les vues rendues) afin qu'elles ne doivent pas être compilées ou redessinées lors des modifications d'état.

http://christopherthielen.github.io/ui-router-extras/

Voici une démo:

http://christopherthielen.github.io/ui-router-extras/example/sticky/#/