De jQuery à JavaScript une référence

Que cela nous plaise ou non, de plus en plus de développeurs se familiarisent avec le monde de JavaScript via jQuery. À bien des égards, ces nouveaux arrivants sont les plus chanceux. Ils ont accès à une pléthore de nouvelles API JavaScript, qui facilitent considérablement le processus de traversée de DOM (ce dont beaucoup de gens dépendent pour jQuery). Malheureusement, ils ne connaissent pas ces API!

Dans cet article, nous allons convertir différentes tâches jQuery communes en JavaScript, qu'il soit moderne ou hérité..

Moderne ou héritage - Pour chaque élément de la liste ci-dessous, vous trouverez la manière moderne et "cool kids" d'accomplir cette tâche, ainsi que l'héritage, "rendre les vieux navigateurs heureux". Le choix que vous choisirez pour vos propres projets dépendra en grande partie de vos visiteurs..


Avant que nous commencions

Veuillez noter que certains des héritage Les exemples de cet article utiliseront un simple navigateur multi-navigateurs., ajouter un évènement une fonction. Cette fonction garantira simplement que le modèle d’événement recommandé par le W3C, addEventListener, et l'héritage d'Internet Explorer attachEvent sont normalisés.

Alors, quand je parle de addEvent (els, event, handler) dans les extraits de code hérités ci-dessous, la fonction suivante est référencée.

var addEvent = (function () var filter = function (el, type, fn) pour (var i = 0, len = el.length; i < len; i++ )  addEvent(el[i], type, fn);  ; if ( document.addEventListener )  return function (el, type, fn)  if ( el && el.nodeName || el === window )  el.addEventListener(type, fn, false);  else if (el && el.length)  filter(el, type, fn);  ;  return function (el, type, fn)  if ( el && el.nodeName || el === window )  el.attachEvent('on' + type, function ()  return fn.call(el, window.event); );  else if ( el && el.length )  filter(el, type, fn);  ; )(); // usage addEvent( document.getElementsByTagName('a'), 'click', fn);

1 - $ ('# conteneur');

Cet appel de fonction interrogera le DOM pour l'élément avec un identifiant de récipient, et créer un nouveau jQuery objet.

JavaScript moderne

var conteneur = document.querySelector ('# conteneur');

querySelector fait partie de l'API Selectors, qui nous permet d'interroger le DOM à l'aide des sélecteurs CSS que nous connaissons déjà.

Cette méthode particulière retournera le premier élément qui correspond au sélecteur passé..

Héritage

var conteneur = document.getElementById ('conteneur');

Portez une attention particulière à la façon dont vous référencez l'élément. Lors de l'utilisation getElementById, vous passez la valeur seul, tandis que, avec querySelector, un sélecteur CSS est attendu.


2 - $ ('# conteneur'). find ('li');

Cette fois, nous ne cherchons pas un seul élément; à la place, nous capturons un nombre quelconque d’éléments de la liste qui sont des descendants de #récipient.

JavaScript moderne

var lis = document.querySelectorAll ('# conteneur li');

querySelectorAll reviendra tout éléments qui correspondent au sélecteur CSS spécifié.

Limites du sélecteur

Bien que presque tous les navigateurs pertinents prennent en charge l’API de sélecteurs, les sélecteurs CSS spécifiques que vous transmettez restent limités aux capacités du navigateur. Traduction: Internet Explorer 8 ne supportera que les sélecteurs CSS 2.1.

Héritage

var lis = document.getElementById ('conteneur'). getElementsByTagName ('li');

3 - $ ('a'). on ('click', fn);

Dans cet exemple, nous attachons un Cliquez sur écouteur d'événement pour toutes les balises d'ancrage sur la page.

JavaScript moderne

[] .forEach.call (document.querySelectorAll ('a'), fonction (el) el.addEventListener ('clic', fonction () // on a cliqué sur l'ancre, false););

L'extrait ci-dessus semble effrayant, mais ce n'est pas si grave. Parce que querySelectorAll retourne un statique NodeList plutôt qu'un Tableau, nous ne pouvons pas accéder directement aux méthodes, comme pour chaque. On y remédie en appelant pour chaque sur le Tableau objet, et en passant les résultats de querySelectorAll comme ce.

Héritage

var anchors = document.getElementsbyTagName ('a'); addEvent (ancres, 'click', fn);

4 - $ ('ul'). on ('click', 'a', fn);

Ahh - cet exemple est légèrement différent. Cette fois, l’extrait de code jQuery utilise la délégation d’événements. le Cliquez sur Le programme d'écoute est appliqué à toutes les listes non ordonnées. Toutefois, la fonction de rappel ne sera déclenchée que si la cible (sur laquelle l'utilisateur a cliqué spécifiquement) est une balise d'ancrage..

JavaScript moderne

document.addEventListener ('click', fonction (e) if (e.target.matchesSelector ('ul a')) // continue, false);

Techniquement, cette méthode JavaScript vanille n’est pas la même que celle de l’exemple jQuery. Au lieu de cela, il attache l'écouteur d'événements directement au document. Il utilise ensuite le nouveau matchsSélecteur méthode pour déterminer si le cible - le noeud sur lequel vous avez cliqué - correspond au sélecteur fourni. De cette façon, nous attachons un seul écouteur d'événement, plutôt que plusieurs..

Veuillez noter qu'au moment d'écrire ces lignes, tous les navigateurs implémentent matchsSélecteur via leurs propres préfixes respectifs: mozMatchesSelector, webkitMatchesSelector, etc. Pour normaliser la méthode, on peut écrire:

var correspond; (function (doc) matches = doc.matchesSelector || doc.webkitMatchesSelector || doc.mozMatchesSelector || doc.oMatchesSelector || doc.msMatchesSelector;) (document.documentElement); document.addEventListener ('click', fonction (e) if (matches.call (e.target, 'ul a')) // procéder, false);

Avec cette technique, dans Webkit, les correspondances feront référence à webkitMatchesSelector, et, dans Mozilla, mozMatchesSelector.

Héritage

var uls = document.getElementsByTagName ('ul'); addEvent (uls, 'click', function () var cible = e.target || e.srcElement; if (cible && target.nodeName === 'A') // continue);

En repli, nous déterminons si le nodeName property (le nom de l'élément cible) est égal à notre requête souhaitée. Portez une attention particulière au fait que les anciennes versions d'Internet Explorer fonctionnent parfois selon leurs propres règles, un peu comme le gamin qui mange du play-doh à l'heure du déjeuner. Vous ne pourrez pas accéder cible directement depuis le un événement objet. Au lieu de cela, vous aurez envie de chercher event.srcElement.


5 - $ ('# box'). addClass ('wrap');

jQuery fournit une API utile pour modifier les noms de classe sur un ensemble d'éléments.

JavaScript moderne

document.querySelector ('# box'). classList.add ('wrap');

Cette nouvelle technique utilise le nouveau classList API à ajouter, retirer, et basculer noms de classe.

var conteneur = document.querySelector ('# box'); container.classList.add ('wrap'); container.classList.remove ('wrap'); container.classList.toggle ('wrap');

Héritage

var box = document.getElementById ('box'), hasClass = fonction (el, cl) var regex = new RegExp ('(?: \\ s | ^)' + cl + '(?: \\ s | $ ) '); return !! el.className.match (regex); , addClass = function (el, cl) el.className + = "+ cl;, removeClass = fonction (el, cl) var regex = new RegExp ('(?: \\ s | ^)' + cl + '(?: \\ s | $)'); el.className = el.className.replace (regex, "); , toggleClass = fonction (el, cl) hasClass (el, cl)? removeClass (el, cl): addClass (el, cl); ; addClass (boîte, "drago"); removeClass (boîte, "drago"); toggleClass (boîte, «drago»); // si l'élément n'a pas de classe 'drago', ajoutez-en une.

La technique de repli nécessite un peu plus de travail, oui?


6 - $ ('# list'). next ();

jQuery's suivant La méthode retournera l’élément qui suit immédiatement l’élément actuel dans l’ensemble encapsulé..

JavaScript moderne

var next = document.querySelector ('# list'). nextElementSibling; // IE9

nextElementSibling se référera spécifiquement à la prochaine élément noeud, plutôt que n'importe quel noeud (texte, commentaire, élément). Malheureusement, Internet Explorer 8 et les versions antérieures ne la prennent pas en charge..

Héritage

var list = document.getElementById ('list'), next = list.nextSibling; // nous voulons le prochain nœud d'élément… pas du texte. while (next.nodeType> 1) next = next.nextSibling;

Il y a plusieurs façons d'écrire cela. Dans cet exemple, nous détectons la nodeType du noeud qui suit l'élément spécifié. Ce pourrait être un texte, un élément ou même un commentaire. Comme nous avons spécifiquement besoin du prochain élément, nous souhaitons un nodeType de 1. Si next.nodeType renvoie un nombre supérieur à 1, nous devrions l'ignorer et continuer, car il s'agit probablement d'un nœud de texte.


7 - $ ('
') .appendTo (' corps ');

En plus d'interroger le DOM, jQuery offre également la possibilité de créer et d'injecter des éléments.

JavaScript moderne

var div = document.createElement ('div'); div.id = 'box'; document.body.appendChild (div);

Cet exemple n’a rien de moderne; c'est ainsi que nous avons accompli le processus de création et d'injection d'éléments dans le DOM pendant très longtemps.

Vous aurez probablement besoin d’ajouter du contenu à l’élément, auquel cas vous pouvez soit utiliser innerHTML, ou createTextNode.

div.appendChild (document.createTextNode ('wacka wacka')); // ou div.innerHTML = 'wacka wacka';

8 - $ (document) .ready (fn)

jQuery's document.ready méthode est incroyablement pratique. Cela nous permet de commencer à exécuter le code dès que possible après le chargement du DOM.

JavaScript moderne

document.addEventListener ('DOMContentLoaded', function () // amusez-vous);

Normalisé dans le cadre de HTML5, le DOMContentLoaded événement se déclenche dès que le document est terminé analysé.

Héritage

// http://dustindiaz.com/smallest-domready-ever function ready (cb) /in/.test(document.readyState) // in = loadINg? setTimeout ('ready (' + cb + ')', 9): cb ();  ready (function () // récupère quelque chose dans le DOM);

La solution de secours, toutes les neuf millisecondes, détectera la valeur de document.readyState. Si "chargement" est renvoyé, le document n'a pas encore été complètement analysé (/in/.test (). Une fois qu'il a, cependant, document.readyState sera égal à "complet", à quel point la fonction de rappel de l'utilisateur est exécutée.


9 - $ ('. box'). css ('color', 'red');

Si possible, ajoutez toujours un classe à un élément, lorsque vous devez fournir un style spécial. Cependant, parfois, le style sera déterminé dynamiquement, auquel cas il doit être inséré en tant qu'attribut.

JavaScript moderne

[] .forEach.call (document.querySelectorAll ('. box'), fonction (el) el.style.color = 'red'; // ou ajouter une classe);

Encore une fois, nous utilisons le [] .forEach.call () technique permettant de filtrer tous les éléments avec une classe de boîte, et les rendre rouges, via le style objet.

Héritage

var box = document.getElementsByClassName ('box'), // reportez-vous à l'exemple n ° 10 ci-dessous pour une solution inter-navigateurs i = box.length; while (i--> 0 && (box [i] .style.color = 'red'));

Cette fois, nous devenons un peu délicats avec le tandis que boucle. Oui, c'est un peu sarcastique, n'est-ce pas? Essentiellement, nous imitons:

var i = 0, len; pour (len = box.length; i < len; i++ )  box[i].style.color = 'red'; 

Toutefois, comme nous n’avons besoin que d’une seule action, nous pouvons enregistrer quelques lignes. Notez que la lisibilité est bien plus importante que la sauvegarde de deux lignes - d’où ma référence "sournoise". Néanmoins, il est toujours amusant de voir à quel point vous pouvez condenser vos boucles. Nous sommes des développeurs. nous faisons ce genre de choses pour le plaisir! Quoi qu’il en soit, n’hésitez pas à vous en tenir à la pour version du relevé.


dix - $ ()

Clairement, notre intention n'est pas de répliquer l'intégralité de l'API jQuery. En règle générale, pour les projets autres que jQuery, la $ ou $$ fonction est utilisée comme raccourci pour récupérer un ou plusieurs éléments du DOM.

JavaScript moderne

var $ = fonction (el) retourne document.querySelectorAll (el); ; // Usage = $ ('. Box');

Remarquerez que $ est simplement un pointeur à un caractère document.querySelector. Ça fait gagner du temps!

Héritage

if (! document.getElementsByClassName) document.getElementsByClassName = fonction (cl, balise) var els, correspond = [], i = 0, len, regex = new RegExp ('(?: \\ s | ^)' + cl + '(?: \\ s | $)'); // Si aucun nom de balise n'est spécifié, // nous devons extraire CHAQUE élément du DOM els = document.getElementsByTagName (tag || "*"); si (! els [0]) renvoie false; pour (len = els.length; i < len; i++ )        if ( els[i].className.match(regex) )           matches.push( els[i]);               return matches; // an array of elements that have the desired classname ;    // Very simple implementation. We're only checking for an id, class, or tag name. // Does not accept CSS selectors in pre-querySelector browsers. var $ = function(el, tag)     var firstChar = el.charAt(0);      if ( document.querySelectorAll ) return document.querySelectorAll(el);      switch ( firstChar )        case "#":          return document.getElementById( el.slice(1) );       case ".":          return document.getElementsByClassName( el.slice(1), tag );       default:          return document.getElementsByTagName(el);     ; // Usage $('#container'); $('.box'); // any element with a class of box $('.box', 'div'); // look for divs with a class of box $('p'); // get all p elements

Malheureusement, la méthode héritée n'est pas aussi minime. Honnêtement, à ce stade, vous devriez utiliser une bibliothèque. jQuery est hautement optimisé pour travailler avec le DOM, c'est pourquoi il est si populaire! L'exemple ci-dessus fonctionnera certainement, cependant, il ne prend pas en charge les sélecteurs CSS complexes dans les anciens navigateurs; cette tâche est un peu plus compliquée!


Résumé

Il est important pour moi de noter que je ne vous encourage pas à abandonner jQuery. Je l'utilise dans presque tous mes projets. Cela dit, ne soyez pas toujours prêt à accepter les abstractions sans prendre un peu de temps pour rechercher le code sous-jacent.

J'aimerais que cette publication serve de document vivant, en quelque sorte. Si vous avez l'un des vôtres (ou des améliorations / clarifications pour mes exemples), laissez un commentaire ci-dessous, et je mettrai sporadiquement à jour cette publication avec de nouveaux éléments. Marquez cette page maintenant! Enfin, je voudrais envoyer un chapeau à cet ensemble d’exemples, qui a servi de moteur à ce poste..