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:
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.
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:
ng-bind
, ng-repeat
et ainsi de suite. J'ai des semi-solutions mais je vais être sévère à propos de mes envies.
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:
Désavantages:
Utilisez Sticky States AND Future States de ui-router-extras qui est génial.
Avantages:
ui-router
. book1
, le book2
mais je ne suis pas sûr de book/1
et de book/2
Désavantages:
(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
- Votre contrôleur, c'est-à-dire BooksController, vérifie si les mêmes données ont été demandées avant,
- Sinon, vous pouvez charger les données via l'appel ajax du serveur et également l'enregistrer dans un stockage local.
- 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/#/