AngularJS vs jQuery
AngularJS et jQuery adoptent des idéologies très différentes. Si vous venez de jQuery, certaines des différences peuvent vous surprendre. Angulaire peut vous mettre en colère.
C'est normal, vous devez pousser à travers. Angulaire en vaut la peine.
La grande différence (TLDR)
jQuery vous donne une boîte à outils pour sélectionner des bits arbitraires du DOM et leur apporter des modifications ad hoc. Vous pouvez faire à peu près tout ce que vous aimez, morceau par morceau.
AngularJS vous donne plutôt un compilateur .
Cela signifie que AngularJS lit l'intégralité de votre DOM de haut en bas et le traite comme du code, littéralement comme des instructions pour le compilateur. En parcourant le DOM, il recherche des directives spécifiques ( directives du compilateur) qui indiquent au compilateur AngularJS comment se comporter et quoi faire. Les directives sont de petits objets pleins de JavaScript qui peuvent correspondre à des attributs, des balises, des classes ou même des commentaires.
Lorsque le compilateur angulaire détermine qu'un morceau du DOM correspond à une directive particulière, il appelle la fonction directive, en lui passant l'élément DOM, tous les attributs, le $ scope actuel (qui est un magasin de variables local) et quelques autres bits utiles. Ces attributs peuvent contenir des expressions qui peuvent être interprétées par la directive et qui lui indiquent comment effectuer le rendu et quand il doit se redessiner.
Les directives peuvent ensuite à leur tour extraire des composants angulaires supplémentaires tels que des contrôleurs, des services, etc. Ce qui sort du bas du compilateur est une application Web entièrement formée, câblée et prête à fonctionner.
Cela signifie que Angular est piloté par modèle . Votre modèle pilote le JavaScript, et non l'inverse. Il s'agit d'un renversement radical des rôles, et l'opposé complet du JavaScript discret que nous écrivons depuis une dizaine d'années. Cela peut prendre un certain temps pour s'y habituer.
Si cela semble être trop contraignant et limitatif, rien ne pourrait être plus éloigné de la vérité. Étant donné qu'AngularJS traite votre code HTML comme du code, vous obtenez une granularité de niveau HTML dans votre application Web . Tout est possible, et la plupart des choses sont étonnamment faciles une fois que vous avez fait quelques sauts conceptuels.
Venons-en aux choses sérieuses.
Tout d'abord, Angular ne remplace pas jQuery
Angular et jQuery font des choses différentes. AngularJS vous fournit un ensemble d'outils pour produire des applications Web. jQuery vous donne principalement des outils pour modifier le DOM. Si jQuery est présent sur votre page, AngularJS l'utilisera automatiquement. Si ce n'est pas le cas, AngularJS est livré avec jQuery Lite, qui est une version réduite, mais toujours parfaitement utilisable de jQuery.
Misko aime jQuery et ne s'oppose pas à ce que vous l'utilisiez. Cependant, vous constaterez à mesure que vous progressez que vous pouvez effectuer à peu près tout votre travail en utilisant une combinaison de portée, de modèles et de directives, et vous devriez préférer ce flux de travail si possible car votre code sera plus discret, plus configurable et plus Angulaire.
Si vous utilisez jQuery, vous ne devriez pas le répandre partout. Le bon endroit pour la manipulation DOM dans AngularJS est dans une directive. Plus sur ces derniers plus tard.
JavaScript discret avec sélecteurs vs modèles déclaratifs
jQuery est généralement appliqué discrètement. Votre code JavaScript est lié dans l'en-tête (ou le pied de page), et c'est le seul endroit où il est mentionné. Nous utilisons des sélecteurs pour sélectionner des parties de la page et écrire des plugins pour modifier ces parties.
Le JavaScript est en contrôle. Le HTML a une existence complètement indépendante. Votre HTML reste sémantique même sans JavaScript. Les attributs Onclick sont une très mauvaise pratique.
L'une des premières choses que vous remarquerez à propos d'AngularJS est que les attributs personnalisés sont partout . Votre HTML sera jonché d'attributs ng, qui sont essentiellement des attributs onClick sur les stéroïdes. Ce sont des directives (directives du compilateur), et sont l'une des principales façons dont le modèle est accroché au modèle.
Lorsque vous voyez cela pour la première fois, vous pourriez être tenté d'écrire AngularJS en tant que JavaScript intrusif de la vieille école (comme je l'ai fait au début). En fait, AngularJS ne respecte pas ces règles. Dans AngularJS, votre HTML5 est un modèle. Il est compilé par AngularJS pour produire votre page Web.
C'est la première grande différence. Pour jQuery, votre page web est un DOM à manipuler. Pour AngularJS, votre code HTML est du code à compiler. AngularJS lit dans votre page Web entière et la compile littéralement dans une nouvelle page Web en utilisant son compilateur intégré.
Votre modèle doit être déclaratif; sa signification doit être claire simplement en la lisant. Nous utilisons des attributs personnalisés avec des noms significatifs. Nous créons de nouveaux éléments HTML, toujours avec des noms significatifs. Un concepteur avec une connaissance HTML minimale et aucune compétence en codage peut lire votre modèle AngularJS et comprendre ce qu'il fait. Il ou elle peut apporter des modifications. C'est la voie angulaire.
Le gabarit est dans le siège conducteur.
L'une des premières questions que je me suis posée lors du démarrage d'AngularJS et de l'exécution des didacticiels est "Où est mon code?" . Je n'ai écrit aucun JavaScript, et pourtant j'ai tout ce comportement. La réponse est évidente. Comme AngularJS compile le DOM, AngularJS traite votre HTML comme du code. Pour de nombreux cas simples, il suffit souvent d'écrire un modèle et de laisser AngularJS le compiler dans une application pour vous.
Votre modèle pilote votre application. Il est traité comme une DSL . Vous écrivez des composants AngularJS, et AngularJS se chargera de les extraire et de les rendre disponibles au bon moment en fonction de la structure de votre modèle. C'est très différent d'un modèle MVC standard , où le modèle est juste pour la sortie.
Il est plus similaire à XSLT qu'à Ruby on Rails par exemple.
Il s'agit d'une inversion de contrôle radicale qui prend un certain temps pour s'y habituer.
Arrêtez d'essayer de piloter votre application à partir de votre JavaScript. Laissez le modèle piloter l'application et laissez AngularJS s'occuper du câblage des composants ensemble. C'est aussi la voie angulaire.
HTML sémantique vs modèles sémantiques
Avec jQuery, votre page HTML doit contenir un contenu significatif sémantique. Si le JavaScript est désactivé (par un utilisateur ou un moteur de recherche), votre contenu reste accessible.
Parce que AngularJS traite votre page HTML comme un modèle. Le modèle n'est pas censé être sémantique car votre contenu est généralement stocké dans votre modèle qui provient finalement de votre API. AngularJS compile votre DOM avec le modèle pour produire une page Web sémantique.
Votre source HTML n'est plus sémantique, au lieu de cela, votre API et DOM compilé sont sémantiques.
Dans AngularJS, ce qui signifie vit dans le modèle, le HTML est juste un modèle, pour l'affichage uniquement.
À ce stade, vous avez probablement toutes sortes de questions concernant le référencement et l'accessibilité, et à juste titre. Il y a des problèmes ouverts ici. La plupart des lecteurs d'écran analysent désormais JavaScript. Les moteurs de recherche peuvent également indexer le contenu AJAXed . Néanmoins, vous voudrez vous assurer que vous utilisez des URL pushstate et que vous avez un plan du site décent. Voir ici pour une discussion du problème: https://stackoverflow.com/a/23245379/687677
Séparation des préoccupations (SOC) vs MVC
La séparation des préoccupations (SOC) est un modèle qui a grandi au cours de nombreuses années de développement Web pour diverses raisons, notamment le référencement, l'accessibilité et l'incompatibilité du navigateur. Cela ressemble à ceci:
- HTML - Signification sémantique. Le HTML doit être autonome.
- CSS - Style, sans le CSS, la page est toujours lisible.
- JavaScript - Comportement, sans le script, le contenu reste.
Encore une fois, AngularJS ne respecte pas ses règles. D'un coup, AngularJS supprime une décennie de sagesse reçue et implémente à la place un modèle MVC dans lequel le modèle n'est plus sémantique, même pas un peu.
Cela ressemble à ceci:
- Modèle - vos modèles contiennent vos données sémantiques. Les modèles sont généralement des objets JSON . Les modèles existent en tant qu'attributs d'un objet appelé $ scope. Vous pouvez également stocker des fonctions utilitaires pratiques sur $ scope auxquelles vos modèles peuvent ensuite accéder.
- Vue - Vos vues sont écrites en HTML. La vue n'est généralement pas sémantique car vos données résident dans le modèle.
- Contrôleur - Votre contrôleur est une fonction JavaScript qui accroche la vue au modèle. Sa fonction est d'initialiser $ scope. Selon votre application, vous pouvez ou non avoir besoin de créer un contrôleur. Vous pouvez avoir plusieurs contrôleurs sur une page.
MVC et SOC ne sont pas aux extrémités opposées de la même échelle, ils sont sur des axes complètement différents. SOC n'a aucun sens dans un contexte AngularJS. Vous devez l'oublier et passer à autre chose.
Si, comme moi, vous avez vécu les guerres des navigateurs, vous pourriez trouver cette idée assez choquante. Dépassez-vous, ça vaudra le coup, je le promets.
Plugins vs directives
Les plugins étendent jQuery. Les directives AngularJS étendent les capacités de votre navigateur.
Dans jQuery, nous définissons les plugins en ajoutant des fonctions au jQuery.prototype. Nous les connectons ensuite au DOM en sélectionnant des éléments et en appelant le plugin sur le résultat. L'idée est d'étendre les capacités de jQuery.
Par exemple, si vous voulez un carrousel sur votre page, vous pouvez définir une liste non ordonnée de figures, peut-être enveloppée dans un élément nav. Vous pouvez ensuite écrire du jQuery pour sélectionner la liste sur la page et la redéfinir comme une galerie avec des délais d'attente pour faire l'animation glissante.
Dans AngularJS, nous définissons des directives. Une directive est une fonction qui renvoie un objet JSON. Cet objet indique à AngularJS quels éléments DOM rechercher et quels changements leur apporter. Les directives sont connectées au modèle à l'aide d'attributs ou d'éléments que vous inventez. L'idée est d'étendre les capacités du HTML avec de nouveaux attributs et éléments.
La méthode AngularJS consiste à étendre les capacités du HTML d'aspect natif. Vous devez écrire du HTML qui ressemble à du HTML, étendu avec des attributs et des éléments personnalisés.
Si vous voulez un carrousel, utilisez simplement un <carousel />
élément, puis définissez une directive pour extraire un modèle et faire fonctionner cette ventouse.
Beaucoup de petites directives contre de gros plugins avec des commutateurs de configuration
La tendance avec jQuery est d'écrire de gros gros plugins comme lightbox que nous configurons ensuite en passant de nombreuses valeurs et options.
C'est une erreur dans AngularJS.
Prenons l'exemple d'une liste déroulante. Lors de l'écriture d'un plugin déroulant, vous pourriez être tenté de coder dans des gestionnaires de clics, peut-être une fonction pour ajouter un chevron qui est soit vers le haut soit vers le bas, peut-être changer la classe de l'élément déplié, afficher masquer le menu, toutes les choses utiles.
Jusqu'à ce que vous vouliez faire un petit changement.
Supposons que vous ayez un menu que vous souhaitez déplier en survol. Eh bien maintenant, nous avons un problème. Notre plugin a câblé notre gestionnaire de clics pour nous, nous allons devoir ajouter une option de configuration pour qu'il se comporte différemment dans ce cas spécifique.
Dans AngularJS, nous écrivons des directives plus petites. Notre directive déroulante serait ridiculement petite. Il peut conserver l'état plié et fournir des méthodes pour fold (), unfold () ou toggle (). Ces méthodes mettraient simplement à jour $ scope.menu.visible qui est un booléen contenant l'état.
Maintenant, dans notre modèle, nous pouvons câbler ceci:
<a ng-click="toggle()">Menu</a>
<ul ng-show="menu.visible">
...
</ul>
Besoin de mettre à jour au survol de la souris?
<a ng-mouseenter="unfold()" ng-mouseleave="fold()">Menu</a>
<ul ng-show="menu.visible">
...
</ul>
Le modèle pilote l'application afin que nous obtenions une granularité de niveau HTML. Si nous voulons faire des exceptions au cas par cas, le modèle rend cela facile.
Clôture vs périmètre $
Les plugins JQuery sont créés dans une fermeture. La confidentialité est maintenue dans cette fermeture. C'est à vous de maintenir votre chaîne de portée dans cette fermeture. Vous n'avez vraiment accès qu'à l'ensemble des nœuds DOM transmis au plug-in par jQuery, ainsi qu'à toutes les variables locales définies dans la fermeture et à tous les globaux que vous avez définis. Cela signifie que les plugins sont assez autonomes. C'est une bonne chose, mais cela peut devenir restrictif lors de la création d'une application entière. Essayer de transmettre des données entre les sections d'une page dynamique devient une corvée.
AngularJS a des objets $ scope. Ce sont des objets spéciaux créés et maintenus par AngularJS dans lesquels vous stockez votre modèle. Certaines directives engendreront une nouvelle portée $ qui, par défaut, héritera de sa portée $ en utilisant l'héritage prototypique JavaScript. L'objet $ scope est accessible dans le contrôleur et la vue.
Ceci est la partie intelligente. Étant donné que la structure de l'héritage de $ scope suit à peu près la structure du DOM, les éléments ont accès à leur propre étendue et à toutes les étendues contenant de manière transparente, jusqu'à la portée globale de $ (qui n'est pas la même que la portée globale).
Cela facilite grandement la transmission des données et le stockage des données à un niveau approprié. Si une liste déroulante est dépliée, seule la portée $ dropdown doit en être informée. Si l'utilisateur met à jour ses préférences, vous souhaiterez peut-être mettre à jour la portée globale $, et toutes les étendues imbriquées écoutant les préférences de l'utilisateur seront automatiquement alertées.
Cela peut sembler compliqué, en fait, une fois que vous vous détendez, c'est comme voler. Vous n'avez pas besoin de créer l'objet $ scope, AngularJS l'instancie et le configure pour vous, correctement et de manière appropriée en fonction de votre hiérarchie de modèles. AngularJS le met ensuite à la disposition de votre composant en utilisant la magie de l'injection de dépendances (plus d'informations à ce sujet plus tard).
Modifications DOM manuelles et liaison de données
Dans jQuery, vous effectuez tous vos changements DOM à la main. Vous construisez de nouveaux éléments DOM par programmation. Si vous avez un tableau JSON et que vous souhaitez le mettre dans le DOM, vous devez écrire une fonction pour générer le HTML et l'insérer.
Dans AngularJS, vous pouvez également le faire, mais nous vous encourageons à utiliser la liaison de données. Modifiez votre modèle, et parce que le DOM y est lié via un modèle, votre DOM se mettra automatiquement à jour, aucune intervention requise.
Étant donné que la liaison de données est effectuée à partir du modèle, à l'aide d'un attribut ou de la syntaxe d'accolade, c'est très facile à faire. Il y a peu de frais généraux cognitifs associés, vous vous retrouverez donc à le faire tout le temps.
<input ng-model="user.name" />
Lie l'élément d'entrée à $scope.user.name
. La mise à jour de l'entrée mettra à jour la valeur dans votre portée actuelle, et vice-versa.
Également:
<p>
{{user.name}}
</p>
affichera le nom d'utilisateur dans un paragraphe. Il s'agit d'une liaison en direct, donc si la $scope.user.name
valeur est mise à jour, le modèle sera également mis à jour.
Ajax tout le temps
Dans jQuery, effectuer un appel Ajax est assez simple, mais c'est toujours quelque chose auquel vous pourriez penser à deux fois. Il y a la complexité supplémentaire à penser et une bonne partie de script à maintenir.
Dans AngularJS, Ajax est votre solution par défaut et cela se produit tout le temps, presque sans que vous ne le remarquiez. Vous pouvez inclure des modèles avec ng-include. Vous pouvez appliquer un modèle avec la directive personnalisée la plus simple. Vous pouvez encapsuler un appel Ajax dans un service et créer vous-même un service GitHub , ou un service Flickr , auquel vous pouvez accéder avec une facilité étonnante.
Objets de service vs fonctions d'assistance
Dans jQuery, si nous voulons accomplir une petite tâche non liée à dom comme extraire un flux d'une API, nous pouvons écrire une petite fonction pour le faire dans notre fermeture. C'est une solution valable, mais que se passe-t-il si nous voulons accéder souvent à ce flux? Et si nous voulons réutiliser ce code dans une autre application?
AngularJS nous donne des objets de service.
Les services sont des objets simples qui contiennent des fonctions et des données. Ce sont toujours des singletons, ce qui signifie qu'il ne peut jamais y en avoir plus d'un. Supposons que nous voulons accéder à l'API Stack Overflow, nous pourrions écrire un StackOverflowService
qui définit les méthodes pour le faire.
Disons que nous avons un panier d'achat. Nous pouvons définir un ShoppingCartService qui gère notre panier et contient des méthodes pour ajouter et supprimer des articles. Étant donné que le service est un singleton et qu'il est partagé par tous les autres composants, tout objet qui doit pouvoir écrire dans le panier et en extraire des données. C'est toujours le même chariot.
Les objets de service sont des composants AngularJS autonomes que nous pouvons utiliser et réutiliser comme bon nous semble. Ce sont de simples objets JSON contenant des fonctions et des données. Ce sont toujours des singletons, donc si vous stockez des données sur un service en un seul endroit, vous pouvez obtenir ces données ailleurs simplement en demandant le même service.
Injection de dépendance (DI) vs instatiation - alias dé-spaghettification
AngularJS gère vos dépendances pour vous. Si vous voulez un objet, référez-vous simplement à lui et AngularJS le trouvera pour vous.
Jusqu'à ce que vous commenciez à l'utiliser, il est difficile d'expliquer à quel point c'est une énorme bénédiction. Rien comme AngularJS DI n'existe dans jQuery.
DI signifie qu'au lieu d'écrire votre application et de la câbler ensemble, vous définissez plutôt une bibliothèque de composants, chacun identifié par une chaîne.
Disons que j'ai un composant appelé «FlickrService» qui définit les méthodes pour extraire les flux JSON de Flickr. Maintenant, si je veux écrire un contrôleur qui peut accéder à Flickr, il me suffit de faire référence au «FlickrService» par son nom lorsque je déclare le contrôleur. AngularJS se chargera d'instancier le composant et de le mettre à disposition de mon contrôleur.
Par exemple, ici je définis un service:
myApp.service('FlickrService', function() {
return {
getFeed: function() { // do something here }
}
});
Maintenant, quand je veux utiliser ce service, je me réfère à lui par son nom comme ceci:
myApp.controller('myController', ['FlickrService', function(FlickrService) {
FlickrService.getFeed()
}]);
AngularJS reconnaîtra qu'un objet FlickrService est nécessaire pour instancier le contrôleur et nous en fournira un.
Cela rend le câblage des choses très facile et élimine à peu près toute tendance à la spagettification. Nous avons une liste plate de composants, et AngularJS nous les remet un par un au fur et à mesure de nos besoins.
Architecture de service modulaire
jQuery en dit très peu sur la façon dont vous devez organiser votre code. AngularJS a des opinions.
AngularJS vous propose des modules dans lesquels vous pouvez placer votre code. Si vous écrivez un script qui parle à Flickr par exemple, vous voudrez peut-être créer un module Flickr pour encapsuler toutes vos fonctions liées à Flickr. Les modules peuvent inclure d'autres modules (DI). Votre application principale est généralement un module, et cela devrait inclure tous les autres modules dont votre application dépendra.
Vous obtenez une réutilisation simple du code, si vous voulez écrire une autre application basée sur Flickr, vous pouvez simplement inclure le module Flickr et le tour est joué, vous avez accès à toutes vos fonctions liées à Flickr dans votre nouvelle application.
Les modules contiennent des composants AngularJS. Lorsque nous incluons un module, tous les composants de ce module deviennent disponibles pour nous comme une simple liste identifiée par leurs chaînes uniques . Nous pouvons ensuite injecter ces composants les uns dans les autres en utilisant le mécanisme d'injection de dépendance d'AngularJS.
Pour résumer
AngularJS et jQuery ne sont pas des ennemis. Il est possible d'utiliser jQuery dans AngularJS très bien. Si vous utilisez bien AngularJS (modèles, liaison de données, $ scope, directives, etc.), vous constaterez que vous avez besoin de beaucoup moins de jQuery que vous ne pourriez en avoir besoin autrement.
La principale chose à réaliser est que votre modèle pilote votre application. Arrêtez d'essayer d'écrire de gros plugins qui font tout. Au lieu de cela, écrivez de petites directives qui font une chose, puis écrivez un modèle simple pour les câbler ensemble.
Pensez moins au JavaScript discret et pensez plutôt aux extensions HTML.
Mon petit livre
Je suis tellement excité à propos d'AngularJS, j'ai écrit un court livre à ce sujet que vous êtes invités à lire en ligne http://nicholasjohnson.com/angular-book/ . J'espère que c'est utile.