Почему нельзя обратиться к элементу по его классу в шаблоне?
Коллеги, привет.
Почему не работает событие на элементе, созданном в рамках шаблона при помощи другого события? Вот забацал латй-код для иллюстрации проблемы Смысл такой. Написал функцию, которая из массива объектов собирает данные, подставляет их в шаблон и аппендит его в секцию DOM-а. В массиве некоторое количество объектов с данными. Задача вывести первый шаблон, полученный из первого объекта массива сразу, т.е. при событии DOMContentLoaded я просто запускаю данную функцию. А далее при клике на ссылку "Ещё..." выводить шаблон, полученный из следующего объекта данного массива объектов, ну и так далее выводить по одному следующие шаблоны. В шаблоне присутствует элемент <a>, на который подвешено событие click, в котором, например, прописано alert('Yo!'); Так вот загвоздка в том, что это событие срабатывает только на первом созданном шаблоне, который генерился при DOMContentLoaded. На последующих шаблонах событие click у данного элемента не срабатывает: const testLinks = document.getElementsByClassName("test-link"); for(let testLink of testLinks) { testLink.addEventListener('click', function(event) { let t = event.target; console.log(t); alert ('Yo!'); }); } Но интересно то, что инспектор видит в доме созданный шаблон, однако показывает, что в самом первом шаблоне на элементе <a> event висит, а на остальных, сгенерированных по событию click ("Ещё..") данного ивента на их элементе <a> нет! (см. пример). И ещё. Проверка на target при делегировании события родителю работает только в том случае, если родитель лежит за пределами генерируемого html-шаблона. Т.е. в случае с body и проверкой на target наличие нужного класса .test-link событие срабатывает. ПОЧЕМУ ТАК ПРОИСХОДИТ?!! ПОМОГИТЕ! В ЧЁМ ЗАГВОЗДКА? ЗЫ: делегирование не подходит мне, так как я на реальном проекте использую сторонние библиотеки, которые ни хрена не отрабатывают события при таком раскладе. Заранее спасибо. |
Vladikslav, Честно говоря не дочитал ваше сообщение, т.к. ответ на вопрос стал ясен после ознакомления с макетом и вашим кодом.
Цитата:
Подгружаемые элементы появятся только после нажатия пользователем на кнопку, ваш код к этому моменту уже отработает. Эту проблему можно решить делегированием слушателя события ближайшему общему родителю для будущих и уже существующих элементов. Гуглите «js event delegation». |
Набросал на коленке примерное решение:
document.addEventListener('DOMContentLoaded', () => { const wrapper = document.querySelector('.objects'); if (!wrapper) return; const selector = '.test-link'; wrapper.addEventListener('click', e => { let target = e.target; if (!target || !target.matches(selector) && !(target = target.closest(selector))) { return; } console.log(target); alert('Yo!'); }); }); |
Цитата:
if (!target || !(target = target.closest(selector))) { (А когда может быть !target ?) |
Цитата:
p.s. спасибо за подсказку с .closest, почему-то не думал, что метод возвращает «ближайший родительский элемент (или сам элемент)». Если предположить, что у события всегда будет свойство target, то условие можно сильно сократить: if (!target.closest(selector)) return; |
Цитата:
Спасибо за разъяснение, зря не дочитали до конца. Цитата:
Цитата:
const a = document.createElement('a'); a.setAttribute('data-fslightbox', 'gallery'); a.setAttribute('href', 'images/2.jpg'); document.body.appendChild(a); refreshFsLightbox(); Магия!!! Ребята позаботились об этом! :dance: https://fslightbox.com/javascript/do...use#refreshing Короче, разобрался с этим сам, можете мне карму повысить, а то я что-то в нулях засиделся здесь почему-то :victory: |
Часовой пояс GMT +3, время: 03:51. |