Passer des paramètres dans L'événement javascript onClick
J'essaie de passer un paramètre dans l'événement onclick. Voici un exemple de code:
<div id="div"></div>
<script language="javascript" type="text/javascript">
var div = document.getElementById('div');
for (var i = 0; i < 10; i++) {
var link = document.createElement('a');
link.setAttribute('href', '#');
link.innerHTML = i + '';
link.onclick= function() { onClickLink(i+'');};
div.appendChild(link);
div.appendChild(document.createElement('BR'));
}
function onClickLink(text) {
alert('Link ' + text + ' clicked');
return false;
}
</script>
Cependant, chaque fois que je clique sur l'un des liens, l'alerte affiche toujours 'Lien 10 cliqué'!
Quelqu'un peut-il me dire ce que je fais mal?
Merci
8 réponses
Cela se produit parce que je propage la portée une fois que la fonction est invoquée. Vous pouvez éviter ce problème en utilisant une fermeture.
for (var i = 0; i < 10; i++) {
var link = document.createElement('a');
link.setAttribute('href', '#');
link.innerHTML = i + '';
link.onclick = (function() {
var currentI = i;
return function() {
onClickLink(currentI + '');
}
})();
div.appendChild(link);
div.appendChild(document.createElement('BR'));
}
Ou si vous voulez une syntaxe plus concise, je vous suggère d'utiliser la solution de Nick Craver.
Cela se produit parce qu'ils font tous référence au même i
variable, qui change chaque boucle, et laissée comme 10
à la fin de la boucle. Vous pouvez le résoudre en utilisant une fermeture comme ceci:
link.onclick = function(j) { return function() { onClickLink(j+''); }; }(i);
Ou this
être le lien vous avez cliqué dans ce gestionnaire, comme ceci:
link.onclick = function(j) { return function() { onClickLink.call(this, j); }; }(i);
link.onclick = function() { onClickLink(i+''); };
Est une fermeture et stocke une référence à la variable i
, pas la valeur que i
contient lorsque la fonction est créée. Une solution serait d'envelopper le contenu de la for
boucle en fonction de cela:
for (var i = 0; i < 10; i++) (function(i) {
var link = document.createElement('a');
link.setAttribute('href', '#');
link.innerHTML = i + '';
link.onclick= function() { onClickLink(i+'');};
div.appendChild(link);
div.appendChild(document.createElement('BR'));
}(i));
Essayez ceci:
<div id="div"></div>
<script language="javascript" type="text/javascript">
var div = document.getElementById('div');
for (var i = 0; i < 10; i++) {
var f = function() {
var link = document.createElement('a');
var j = i; // this j is scoped to our anonymous function
// while i is scoped outside the anonymous function,
// getting incremented by the for loop
link.setAttribute('href', '#');
link.innerHTML = j + '';
link.onclick= function() { onClickLink(j+'');};
div.appendChild(link);
div.appendChild(document.createElement('br')); // lower case BR, please!
}(); // call the function immediately
}
function onClickLink(text) {
alert('Link ' + text + ' clicked');
return false;
}
</script>
Ou vous pouvez utiliser cette ligne:
link.setAttribute('onClick', 'onClickLink('+i+')');
Au lieu de celui-ci:
link.onclick= function() { onClickLink(i+'');};
Un autre moyen simple (pourrait ne pas être la meilleure pratique) mais fonctionne comme charm. Construisez la balise HTML de votre élément(lien hypertexte ou bouton) dynamiquement avec javascript, et peut également passer plusieurs paramètres.
// variable to hold the HTML Tags
var ProductButtonsHTML ="";
//Run your loop
for (var i = 0; i < ProductsJson.length; i++){
// Build the <input> Tag with the required parameters for Onclick call. Use double quotes.
ProductButtonsHTML += " <input type='button' value='" + ProductsJson[i].DisplayName + "'
onclick = \"BuildCartById('" + ProductsJson[i].SKU+ "'," + ProductsJson[i].Id + ")\"></input> ";
}
// Add the Tags to the Div's innerHTML.
document.getElementById("divProductsMenuStrip").innerHTML = ProductButtonsHTML;
Il est probablement préférable de créer une fonction dédiée pour créer le lien afin d'éviter de créer deux fonctions anonymes. Ainsi:
<div id="div"></div>
<script>
function getLink(id)
{
var link = document.createElement('a');
link.setAttribute('href', '#');
link.innerHTML = id;
link.onclick = function()
{
onClickLink(id);
};
link.style.display = 'block';
return link;
}
var div = document.getElementById('div');
for (var i = 0; i < 10; i += 1)
{
div.appendChild(getLink(i.toString()));
}
</script>
Bien que dans les deux cas, vous vous retrouvez avec deux fonctions, je pense juste qu'il est préférable de l'envelopper dans une fonction sémantiquement plus facile à comprendre.
Onclick vs addEventListener. Une question de préférence peut-être (où IE > 9).
// Using closures
function onClickLink(e, index) {
alert(index);
return false;
}
var div = document.getElementById('div');
for (var i = 0; i < 10; i++) {
var link = document.createElement('a');
link.setAttribute('href', '#');
link.innerHTML = i + '';
link.addEventListener('click', (function(e) {
var index = i;
return function(e) {
return onClickLink(e, index);
}
})(), false);
div.appendChild(link);
div.appendChild(document.createElement('BR'));
}
Comment buter juste en utilisant un attribut data-* simple, pas aussi cool qu'une fermeture, mais..
function onClickLink(e) {
alert(e.target.getAttribute('data-index'));
return false;
}
var div = document.getElementById('div');
for (var i = 0; i < 10; i++) {
var link = document.createElement('a');
link.setAttribute('href', '#');
link.setAttribute('data-index', i);
link.innerHTML = i + ' Hello';
link.addEventListener('click', onClickLink, false);
div.appendChild(link);
div.appendChild(document.createElement('BR'));
}