J'ai souvent entendu dire que l'utilisation d'événements JavaScript, tels que onClick()
, en HTML, est une mauvaise pratique, car ce n'est pas bon pour la sémantique. Je voudrais savoir quels sont les inconvénients et comment corriger le code suivant?
<a href="#" onclick="popup('/map/', 300, 300, 'map'); return false;">link</a>
javascript
html
NiLL
la source
la source
#
, quiconque choisit de désactiver javascript sera bloqué et incapable de faire quoi que ce soit. Pour certains sites, c'est une bonne chose, mais pour simplement ouvrir une fenêtre, il est tout simplement stupide de ne pas fournir un "vrai" lien.<button>
, car les liens sont censés pointer vers une ressource réelle. C'est plus sémantique de cette façon et plus clair pour les utilisateurs de lecteurs d'écran.Réponses:
Vous parlez probablement de Javascript discret , qui ressemblerait à ceci:
avec la logique dans un fichier javascript central ressemblant à ceci:
Les avantages sont
la source
onClick
. Vous pouvez également écrire des tests unitaires si vous le souhaitez par rapport à vos scripts, ce qui est également très difficile à supposer si le code est à l'intérieur d'unonClick
et qu'aucune logique n'est séparée. Personnellement, je n'ai aucun problème à déboguer un JavaScript discret et les avantages de la gestion et du test du code JavaScript sont bien trop grands pour ne pas l'utiliser.onclick
peut cartographier plus explicitement les relations causales entre l'interaction de l'élément et l'effet (appel de fonction) ainsi que réduire la charge cognitive. De nombreuses leçons plongent les apprenants dans ceaddEventListener
qui contient beaucoup plus d'idées dans une syntaxe plus difficile. De plus, les cadres récents basés sur des composants tels que Riot et React utilisent l'onclick
attribut et changent la notion de ce que devrait être la séparation. Le transfert du HTMLonclick
vers un composant qui prend en charge cela peut être un processus d'apprentissage plus efficace.Si vous utilisez jQuery, alors:
HTML:
JS:
Cela a l'avantage de fonctionner toujours sans JS, ou si l'utilisateur clique du milieu sur le lien.
Cela signifie également que je pourrais gérer les popups génériques en réécrivant à nouveau dans:
HTML:
JS:
Cela vous permettrait d'ajouter un popup à n'importe quel lien en lui donnant simplement la classe popup.
Cette idée pourrait être étendue encore plus loin comme ceci:
HTML:
JS:
Je peux maintenant utiliser le même morceau de code pour beaucoup de popups sur tout mon site sans avoir à écrire des tas de trucs onclick! Yay pour la réutilisabilité!
Cela signifie également que si plus tard je décide que les popups sont une mauvaise pratique, (ce qu'ils sont!) Et que je veux les remplacer par une fenêtre modale de style lightbox, je peux changer:
à
et tous mes popups sur tout mon site fonctionnent maintenant de manière totalement différente. Je pourrais même faire une détection de fonctionnalités pour décider quoi faire sur une fenêtre contextuelle, ou stocker une préférence d'utilisateurs pour les autoriser ou non. Avec le onclick en ligne, cela nécessite un énorme effort de copie et de collage.
la source
Avec de très grandes applications JavaScript, les programmeurs utilisent plus d'encapsulation de code pour éviter de polluer la portée globale. Et pour rendre une fonction disponible à l'action onClick dans un élément HTML, elle doit être dans la portée globale.
Vous avez peut-être vu des fichiers JS qui ressemblent à ceci ...
Il s'agit d'expressions de fonction immédiatement appelées (IIFE) et toute fonction déclarée à l'intérieur n'existera que dans leur portée interne.
Si vous déclarez
function doSomething(){}
dans un IIFE, puis effectuezdoSomething()
l'action onClick d'un élément dans votre page HTML, vous obtiendrez une erreur.Si, d'un autre côté, vous créez un eventListener pour cet élément dans cet IIFE et appelez
doSomething()
lorsque l'écouteur détecte un événement de clic, vous êtes bon car l'auditeur etdoSomething()
partage la portée de l'IIFE.Pour les petites applications Web avec une quantité minimale de code, cela n'a pas d'importance. Mais si vous aspirez à écrire des bases de code volumineuses et maintenables,
onclick=""
c'est une habitude que vous devriez éviter.la source
Ce n'est pas bon pour plusieurs raisons:
eval
Le plus simple serait d'ajouter un
name
attribut à votre<a>
élément, alors vous pourriez faire:bien que la meilleure pratique moderne consiste à utiliser un
id
au lieu d'un nom, et à utiliseraddEventListener()
au lieu d'utiliseronclick
puisque cela vous permet de lier plusieurs fonctions à un seul événement.la source
addEventListener()
, et pourquoi.Il y a quelques raisons:
Je trouve que cela facilite la maintenance pour séparer le balisage, c'est-à-dire les scripts HTML et côté client. Par exemple, jQuery facilite l'ajout de gestionnaires d'événements par programme.
L'exemple que vous donnez serait interrompu dans tout agent utilisateur qui ne prend pas en charge le javascript ou qui a désactivé javascript. Le concept d' amélioration progressive encouragerait un simple lien hypertexte vers
/map/
pour les agents utilisateurs sans javascript, puis l'ajout d'un gestionnaire de clics prgramatiquement pour les agents utilisateurs prenant en charge le javascript.Par exemple:
Balisage:
Javascript:
la source
<a href="https://stackoverflow.com/map/" onclick="popup('/map/', 300, 300, 'map'); return false;">link</a>
Révision
L' approche JavaScript discrète était bonne dans le PASSÉ - en particulier la liaison du gestionnaire d'événements en HTML était considérée comme une mauvaise pratique (principalement parce
onclick events run in the global scope and may cause unexpected error
que ce qui était mentionné par YiddishNinja )Toutefois...
Actuellement, il semble que cette approche soit un peu dépassée et nécessite une mise à jour. Si quelqu'un veut être un développeur frontend professionnel et écrire des applications volumineuses et compliquées, il doit utiliser des frameworks tels que Angular, Vue.js, etc ... Cependant, ces frameworks utilisent généralement (ou permettent d'utiliser) des modèles HTML où les gestionnaires d'événements sont liés dans le code de modèle html directement et c'est très pratique, clair et efficace - par exemple, dans un modèle angulaire, les gens écrivent généralement:
En js / html brut, l'équivalent de ceci sera
La différence est que l'
onclick
événement js brut est exécuté dans la portée globale - mais les frameworks fournissent une encapsulation.Alors, où est le problème?
Le problème est quand un programmeur novice qui a toujours entendu dire que html-onclick est mauvais et qui utilise toujours
btn.addEventListener("onclick", ... )
veut utiliser un cadre avec des modèles (aaddEventListener
également des inconvénients - si nous mettons à jour le DOM de manière dynamique en utilisantinnerHTML=
(ce qui est assez rapide ) - alors nous perdons des événements les gestionnaires se lient de cette manière). Ensuite, il fera face à quelque chose comme de mauvaises habitudes ou une mauvaise approche de l'utilisation du framework - et il utilisera le framework d'une très mauvaise manière - car il se concentrera principalement sur la partie js et non sur la partie modèle (et produira des éléments peu clairs et difficiles à maintenir. code). Pour changer ces habitudes, il perdra beaucoup de temps (et il aura probablement besoin d'un peu de chance et d'enseignant).Donc, à mon avis, sur la base de l'expérience avec mes étudiants, mieux serait pour eux s'ils utilisent html-handlers-bind au début. Comme je l'ai dit, il est vrai que les gestionnaires sont appelés dans une portée globale, mais à ce stade, les étudiants créent généralement de petites applications faciles à contrôler. Pour écrire des applications plus volumineuses, ils choisissent des frameworks.
Alors que faire?
Nous pouvons METTRE À JOUR l'approche JavaScript discrète et autoriser les gestionnaires d'événements de liaison (éventuellement avec des paramètres simples) en html (mais uniquement le gestionnaire de liaison - pas de logique dans onclick comme dans OP quesiton). Donc, à mon avis, en js / html brut, cela devrait être autorisé
ou
Afficher l'extrait de code
Mais les exemples ci-dessous ne doivent PAS être autorisés
La réalité change, notre point de vue devrait aussi
la source
addEventListener
. Ad 2. Oui, ils peuvent être écrasés (mais généralement personne ne le fait) - où est le problème? Ad 3. Handler ne sera pas renvoyé après suppression onclick attrib - preuve iciC'est un
nouveauparadigme appelé " JavaScript discret ". Le "standard Web" actuel dit de séparer la fonctionnalité et la présentation.Ce n'est pas vraiment une "mauvaise pratique", c'est juste que la plupart des nouvelles normes veulent que vous utilisiez des écouteurs d'événements au lieu de JavaScript intégré.
En outre, cela peut être juste une chose personnelle, mais je pense que c'est beaucoup plus facile à lire lorsque vous utilisez des écouteurs d'événements, surtout si vous avez plus d'une instruction JavaScript que vous souhaitez exécuter.
la source
Votre question déclenchera une discussion, je suppose. L'idée générale est qu'il est bon de séparer le comportement et la structure. De plus, afaik, un gestionnaire de clics en ligne doit être
eval
amené à «devenir» une véritable fonction javascript. Et c'est assez démodé, même si c'est un argument assez fragile. Ah, eh bien, lisez-en quelques-uns à ce sujet @ quirksmode.orgla source
performances et l'efficacité.
la source
Deux autres raisons de ne pas utiliser de gestionnaires en ligne:
Ils peuvent nécessiter un devis fastidieux pour échapper à des problèmes
Étant donné une chaîne arbitraire , si vous voulez être en mesure de construire un gestionnaire en ligne qui appelle une fonction avec cette chaîne, pour la solution générale, vous devrez échapper les délimiteurs d' attribut (avec l'entité HTML associée), et vous doivent échapper au délimiteur utilisé pour la chaîne à l'intérieur de l'attribut, comme suit:
C'est incroyablement moche. À partir de l'exemple ci-dessus, si vous ne remplacez pas le
'
s, une SyntaxError en résultera, car laalert('foo'"bar')
syntaxe n'est pas valide. Si vous ne remplacez pas le"
s, le navigateur l'interpréterait comme une fin de l'onclick
attribut (délimité par"
s ci-dessus), ce qui serait également incorrect.Si l'on utilise habituellement des gestionnaires en ligne, il faudrait s'assurer de se rappeler de faire quelque chose de similaire à ce qui précède (et de le faire correctement ) à chaque fois , ce qui est fastidieux et difficile à comprendre en un coup d'œil. Mieux vaut éviter complètement les gestionnaires en ligne pour que la chaîne arbitraire puisse être utilisée dans une simple fermeture:
N'est-ce pas tellement plus agréable?
La chaîne de portée d'un gestionnaire en ligne est extrêmement particulière
Que pensez-vous que le code suivant enregistrera?
Essayez-le, exécutez l'extrait. Ce n'est probablement pas ce à quoi vous vous attendiez. Pourquoi produit-il ce qu'il fait? Parce que les gestionnaires en ligne s'exécutent à l'intérieur de
with
blocs. Le code ci-dessus se trouve dans troiswith
blocs: un pour ledocument
, un pour le<form>
et un pour le<button>
:Afficher l'extrait de code
Puisqu'il
disabled
s'agit d'une propriété du bouton, le référencementdisabled
à l'intérieur du gestionnaire en ligne fait référence à la propriété du bouton et non à ladisabled
variable externe . C'est assez contre-intuitif.with
a de nombreux problèmes: il peut être la source de bogues déroutants et ralentit considérablement le code. Ce n'est même pas du tout autorisé en mode strict. Mais avec les gestionnaires en ligne, vous êtes obligé d'exécuter le code viawith
s - et pas seulement via unwith
, mais via plusieurswith
s imbriqués . C'est fou.with
ne doit jamais être utilisé dans le code. Étant donné que les gestionnaires en ligne exigent implicitementwith
avec tout son comportement déroutant, les gestionnaires en ligne doivent également être évités.la source