Передача параметров в событии Javascript onClick
Я пытаюсь передать параметр в событии onclick. Ниже приведен пример кода:
<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>
Однако всякий раз, когда я нажимаю на любую из ссылок, предупреждение всегда показывает "Ссылка 10 нажата"!
Может ли кто-нибудь сказать мне, что я делаю неправильно?
Спасибо
Ответы
Ответ 1
Это происходит из-за того, что я распространяется до области, как только функция вызывается. Вы можете избежать этой проблемы, используя закрытие.
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'));
}
Или, если вы хотите более сжатый синтаксис, я предлагаю вам использовать решение Nick Craver.
Ответ 2
Это происходит потому, что все они ссылаются на одну и ту же переменную i
, которая меняет каждый цикл и остается как 10
в конце цикла. Вы можете решить эту проблему, используя следующее закрытие:
link.onclick = function(j) { return function() { onClickLink(j+''); }; }(i);
Вы можете попробовать здесь
Или сделайте this
ссылкой, которую вы нажали в этом обработчике, например:
link.onclick = function(j) { return function() { onClickLink.call(this, j); }; }(i);
Вы можете попробовать эту версию здесь
Ответ 3
link.onclick = function() { onClickLink(i+''); };
Является закрытием и сохраняет ссылку на переменную i
, а не значение, которое i
выполняется при создании функции. Одним из решений было бы обернуть содержимое цикла for
в функции:
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));
Ответ 4
Попробуйте следующее:
<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>
Ответ 5
или вы можете использовать эту строку:
link.setAttribute('onClick', 'onClickLink('+i+')');
вместо этого:
link.onclick= function() { onClickLink(i+'');};
Ответ 6
Еще один простой способ (может быть, не лучшая практика), но работает как шарм. Создайте HTML-тег своего элемента (hyperLink или Button) динамически с помощью javascript и также можете передавать несколько параметров.
// 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 innerHTML.
document.getElementById("divProductsMenuStrip").innerHTML = ProductButtonsHTML;
Ответ 7
Вероятно, лучше создать специальную функцию для создания ссылки, чтобы избежать создания двух анонимных функций. Таким образом:
<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>
Хотя в обоих случаях вы получаете две функции, я просто думаю, что лучше обернуть ее в функцию, которая семантически легче понять.
Ответ 8
onclick vs addEventListener. Возможно, предпочтительнее (где 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'));
}
Как просто использовать простой атрибут data- *, а не такой классный, как закрытие, но..
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'));
}