En tant qu'excellent framework Web, AnglarJS peut grandement simplifier le fardeau du développement front-end. Sebastian Fröstl a récemment déclaré dans un article de blog "AngularJS Performance Tuning for Long Lists" qu'AnglarJS s'exécute très lentement lors du traitement de grandes listes contenant des structures de données complexes. Il a également partagé la solution dans l'article. Vous trouverez ci-dessous une traduction de l'article.
AnglarJS est génial, mais il s'exécute très lentement lorsqu'il s'agit de grandes listes contenant des structures de données complexes. Il s'agit d'un problème que nous avons rencontré lors de la migration de la page d'administration principale vers AngularJS. Ces pages devraient fonctionner correctement lors de l'affichage de 500 lignes de données, mais le temps de rendu de la première méthode a pris 7 secondes épouvantables.
Plus tard, nous avons découvert qu'il y avait deux problèmes de performances principaux lors du processus de mise en œuvre. L'une est liée à la directive "ng-repeat" et l'autre est liée aux filtres.
Ci-dessous, nous partagerons notre expérience dans la résolution de problèmes de performances par différentes méthodes, dans l'espoir de vous inspirer.
1. Pourquoi ng-repeat dans AngularJS ralentit-il lors du traitement de grandes listes ?
ng-repeat dans AngularJS ralentira lors du traitement de plus de 2 500 liaisons de données bidirectionnelles. Cela est dû au fait qu'AngularJS détecte les changements via la fonction « dirty checking ». Chaque vérification prend du temps, donc les grandes listes contenant des structures de données complexes ralentiront votre application.
2. Prérequis pour améliorer les performances
Commande d'enregistrement du temps
Afin de mesurer le temps nécessaire au rendu d'une liste, nous avons écrit un programme simple pour enregistrer le temps en utilisant l'attribut "$last" de "ng-repeat". L'heure est stockée dans le service TimeTracker, de sorte que l'enregistrement du temps est séparé du chargement des données côté serveur.
// Directive de répétition de publication pour enregistrer le temps de rendu angulaire.module('siApp.services').directive('postRepeatDirective', ['$timeout', '$log', 'TimeTracker', function($timeout, $log, TimeTracker) { return function(scope, element, attrs) { if (scope.$last){ $timeout(function(){ var timeFinishedLoadingList = TimeTracker.reviewListLoaded(); var ref = new Date(timeFinishedLoadingList); var end = new Date(); $log.debug("## La liste de rendu DOM a pris : " (end - ref) " ms" } } } ]); >
Propriété Timeline des outils de développement ChromeDans l'onglet Chronologie des outils de développement Chrome, vous pouvez voir les événements, les images du navigateur par seconde et les allocations de mémoire. L'outil "mémoire" permet de détecter les fuites mémoire et la mémoire requise par les pages. Le problème de scintillement des pages se produit lorsque la fréquence d'images est inférieure à 30 images par seconde. L'outil « frames » peut aider à comprendre les performances de rendu et peut également afficher le temps CPU passé par une tâche JavaScript.
3. Réglage de base en limitant la taille de la liste
La meilleure façon d'atténuer ce problème est de limiter la taille de la liste affichée. Ceci peut être réalisé par la pagination et l'ajout de barres de défilement infinies.Pagination
Pour la pagination, nous pouvons utiliser le filtre « limitTo » d'AngularJS (AngularJS version 1.1.4 et versions ultérieures) et le filtre « startFrom ». Vous pouvez réduire le temps de rendu en limitant la taille de la liste d'affichage. C'est le moyen le plus efficace de réduire le temps de rendu.
// Pagination dans le contrôleur $scope.currentPage = 0; $scope.pageSize = 75; $scope.numberOfPages = function() { return Math.ceil($scope.displayedItemsList.length/ $scope.pageSize ); ; // Démarrer à partir du filtre angulaire.module('app').filter('startFrom', function() { return function(input, start) { return input.slice(start); }; // Utilisation en HTML // Boutons de pagination{{$index 1}}
Si vous ne pouvez/ne voulez pas utiliser la pagination, mais que le processus de filtrage est très lent, assurez-vous de vérifier les cinq premières étapes et d'utiliser « ng-show » pour masquer les éléments de liste redondants.
Barre de défilement infinie
Si vous souhaitez en savoir plus sur cette méthode, vous pouvez visiter
http://binarymuse.github.io/ngInfiniteScroll/
4. Sept règles de réglage
1. Afficher une liste sans liaison de donnéesC'est la solution la plus évidente puisque la liaison de données est la source la plus probable de problèmes de performances. Si vous souhaitez afficher la liste une seule fois et n'avez pas besoin de mettre à jour ou de modifier les données, renoncer à la liaison de données est une excellente solution. Malheureusement, vous perdez le contrôle de vos données, mais nous n’avons d’autre choix que d’utiliser cette loi. En savoir plus :
https://github.com/Pasvaz/bindonce.
2. N'utilisez pas de méthodes en ligne pour calculer les donnéesPour filtrer la liste directement dans le contrôleur, n'utilisez pas de méthodes qui obtiennent des liens de filtrage. "ng-repeat" évalue chaque [$digest(
http://docs.angularjs.org/api/ng.$rootScope.Scope#$digest)] expression. Dans notre cas, "filteredItems()" renvoie des liens filtrés. Si le processus d’évaluation est lent, cela ralentira rapidement l’ensemble de la candidature.
//Ce n'est pas une bonne méthode car elle nécessite une évaluation fréquente.
//C'est la méthode à utiliser
3. Utilisez deux listes (une pour l'affichage de la vue et une comme source de données)
Séparer la liste à afficher de la liste globale des données est un modèle très utile. Vous pouvez prétraiter certains filtres et appliquer des liens stockés dans le cache aux vues. Le cas suivant montre le processus de mise en œuvre de base. La variable filteredLists contient les liens dans le cache et la méthode applyFilter gère le mappage.
/* Contrôleur */ // Liste de base var items = [{name:"John", active:true}, {name:"Adam"}, {name:"Chris"}, {name:"Heather" }]; // Init displayList $scope.displayedItems = items; // Filtrer le cache var filteredLists['active'] = $filter('filter)(items, {"active" : true}); scope.applyFilter = function(type) { if (filteredLists.hasOwnProperty(type){ // Vérifier si le filtre est mis en cache $scope.displayedItems = filteredLists[type]; } else { /* Filtrage non mis en cache */ } } // Réinitialiser filter $scope.resetFilter = function() { $scope.displayedItems = items } /* View */Select active
{{item.name}}
4. Utilisez ng-if dans d'autres modèles au lieu de ng-show
Si vous utilisez des instructions ou des modèles pour afficher des informations supplémentaires, par exemple en cliquant pour afficher les informations détaillées d'un élément de liste, assurez-vous d'utiliser ng-if (AngularJSv. 1.1.5 et versions ultérieures). ng-if empêche le rendu (par rapport à ng-show). Ainsi, d'autres liaisons DOM et de données peuvent être évaluées selon les besoins.
Le contenu ci-dessus vous donne une explication détaillée de 7 suggestions pour l'optimisation des performances d'AngularJS. J'espère qu'il vous plaira.