Заменяются параметры в onclick при динамическом создании объектов <a/> JavaScript [дубликат]

177
24 февраля 2019, 06:00

На данный вопрос уже ответили:

  • Почему асинхронная функция внутри цикла выполняет последнюю итерацию много раз? 2 ответа

есть функция в HTML коде, она создаёт динамически таблицу для странички, и на элемент в таблице нужно поставить в процессе создания обработку события, onclick, таких элементов МНОГО в таблице, все с разными id по типу: linck01, linck02 ... и т.д. Вот что пытался использовать

a.addEventListener("click", function (){ 
    clickLink(packege, a, id); 
}) 
 
a.onclick = function () { 
    clickLink(packege, a, id); 
}; 
 
//iter и i это те самые цифры 
$("#links_d" + iter.toString() + i.toString()).click(function () 
{ 
    clickLink(packege, a, id); 
}); 
 
var links_d = tr.childNodes[4]; 
links_d = links_d.getElementsByClassName("links") 
links_d[0].onclick = function () { 
    clickLink(packege, links_d[0], id.toString()); 
};

в первом и последнем добавляет, но отрабатывает так что на всех элементах висит функция с последними параметрами, а не теми что передались (packege, a, id), как передать в функцию индивидуальные параметры.

Answer 1

Скорее всего, проблема сводится к следующей ситуации:

for (var i = 1; i <= 3; i++) { 
  $("#link" + i).on("click", function() { 
    clickLink(i); 
  }); 
} 
 
function clickLink(index) { 
  console.log(index); 
}
<div id="link1">Link 1</div> 
<div id="link2">Link 2</div> 
<div id="link3">Link 3</div> 
 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

где всегда будет выводиться 4, так как на момент вызова функции обработчика i как раз и равняется 4

Исправить это можно, например, "захватом" текущего значения i:

for (var i = 1; i <= 3; i++) { 
  (function(index) { 
    $("#link" + i).on("click", function() { 
      clickLink(index); 
    }); 
  })(i); 
} 
 
function clickLink(index) { 
  console.log(index); 
}
<div id="link1">Link 1</div> 
<div id="link2">Link 2</div> 
<div id="link3">Link 3</div> 
 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Answer 2

Можно навесить обработчик через document, тогда не нужно будет навешивать обработчики на динамически созданные элементы. При таком подходе вообще не придется навешивать обработчик в цикле и проблемы со счетчиком не возникнет в принципе, а код будет меньше по объему и проще для понимания.

$(document).on('click', '.links', (e) => {
    let packege = 1; //вычисляем при необходимости
    clickLink(packege, e.currentTarget, e.currentTarget.id.toString());
});

Еще как вариант, вообще навесить обработчик по ссылке:

$(document).on('click', '.links', clickLink);

А всю логику получения параметров перенести в функцию clickLink, через неявно передаваемый объект event.

Если же очень хочется отставить все как есть, то самым быстрым решением будет использовать let вместо var при объявлении счетчиков в циклах.

READ ALSO
Контент меню по всей ширине страницы

Контент меню по всей ширине страницы

Нужно, чтобы блок с зеленой обводкой был по всей ширине страницы (нужно чтобы именно цвет фона был по всей ширине), а сам контент был в соответствии...

151
Помогите с телефонной формой [закрыт]

Помогите с телефонной формой [закрыт]

запланирована форма для отправки телефона на сервер ( это всё есть ) Верстальщик с меня конечно не ахти, можете глянуть и исправить

165
Растягивается слайдер во flexbox контейнере

Растягивается слайдер во flexbox контейнере

Если поместить слайдер во flexbox-элемент, у которого задано свойство flex-grow: 1, слайдер неверно считает ширину и вылазит далеко за пределы элемента,...

131
jquery is not defined

jquery is not defined

Пытаюсь подключить плагин, чтобы на сайте была возможность включить версию для слабовидящих

193