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..
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);
$ ('# 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.
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é..
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.
$ ('# 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
.
var lis = document.querySelectorAll ('# conteneur li');
querySelectorAll
reviendra tout éléments qui correspondent au sélecteur CSS spécifié.
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.
var lis = document.getElementById ('conteneur'). getElementsByTagName ('li');
$ ('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.
[] .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
.
var anchors = document.getElementsbyTagName ('a'); addEvent (ancres, 'click', fn);
$ ('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..
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
.
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
.
$ ('# box'). addClass ('wrap');
jQuery fournit une API utile pour modifier les noms de classe sur un ensemble d'éléments.
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');
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?
$ ('# list'). next ();
jQuery's suivant
La méthode retournera l’élément qui suit immédiatement l’élément actuel dans l’ensemble encapsulé..
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..
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.
$ ('') .appendTo (' corps ');
En plus d'interroger le DOM, jQuery offre également la possibilité de créer et d'injecter des éléments.
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';
$ (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.
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é.
// 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.
$ ('. 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.
[] .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.
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é.
$ ()
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.
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!
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!
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..