Listener's - срабатывает только последний
Добрый день.
Мне нужно вставлять в DOM, узлы в виде строк, и привешивать к ним listener's. Вставляю через innerHTML, на практике, работают listener's только из последней вставки. Упрощённо: <div id='main'></div> <div id='out'></div> <script> function out(data) { document.getElementById('out').innerHTML += data; } var main = document.getElementById('main'); function module1() { main.innerHTML = '<div id="first">Some text, id=first </div><br />'; document.getElementById('first').addEventListener('click', function() { out('clicked on first id '); }); } function module2() { main.innerHTML += '<div id="second">Some text, id=second </div><br />'; document.getElementById('second').addEventListener('click', function() { out('clicked on second id '); }); } module1(); module2(); </script> Возможно при применении +=innerHTML затираются более ранние listener's? Но в документации ничего не нашёл... Как это исправить / решить / обойти? |
Цитата:
Ты просто создаешь новые элементы. А у них нет обработчиков. Вот твой аналог <div id='main'></div> <div id='out'></div> <script> var main = document.getElementById('main'); module1(); module2(); function module1() { main.innerHTML = '<div id="first">Some text, id=first </div><br />'; alert(document.getElementById('first')) document.getElementById('first').addEventListener('click', function() { out('clicked on first id '); }); } function module2() { main.innerHTML = '<div id="first">Some text, id=first </div><br />' + '<div id="second">Some text, id=second </div><br />'; document.getElementById('second').addEventListener('click', function() { out('clicked on second id '); }); } function out(data) { document.getElementById('out').innerHTML += data; } </script> |
Как сделать по другому?
Можно конечно всех listener's добавлять после, но их придётся собирать из разных модулей, что сделает структуру запутанной.
Делать из стринга узлы, а потом добавлять через appendChild? Какой-то кривой путь получается, да и не понятно, "слушатели" останутся ли в этом случае? Других идей как реализовать пока нет. Может у вас есть? |
ksa, что значит не затираются, если затираются? Зачем путать человека, придираясь к словам.)
__Alex__, если так хочешь добавлять именно html как строку - используй метод .insertAdjacentHTML(). Однако, имхо, в твоём случае отлично бы подошёл createElement - не надо было бы переполучать только что созанный элемент, чтоб навесить на него обработчик. Вообще тебе надо чётко представлять, что страница хранится в памяти в виде DOM - связанной структуры объектов и взаимодействия через createElement, appendChild и прочее - наиболее естественный способ. Строки же html существуют только на этапе загрузки странцы до преобразования текста в DOM. После этого любые обращения к innerHTML требуют сериализации и десериализации. |
Цитата:
Но меняя innerHTML создаются другие элементы, а у них обработчиков нет. |
Цитата:
|
<div id='main'></div> <div id='out' style="color:red"></div> <button id='add'>add item</button> <button id='remove'>remove last</button> <script> var callback = (mutationsList) => { for (var mutation of mutationsList) { // если добавление или удаление Node if (mutation.type === 'childList') { // если добавление if (mutation.addedNodes.length > 0) { let [firstnode] = mutation.addedNodes firstnode.addEventListener('click', click) } else if (mutation.removedNodes.length > 0) { // если удаление let [firstnode] = mutation.removedNodes firstnode.removeEventListener('click', click) } } } } var main = document.getElementById('main') var observer = new MutationObserver(callback) var config = { attributes: false, childList: true, subtree: false } observer.observe(main, config) var click = (e) => document.getElementById('out').innerHTML = e.target.id document.getElementById('add').addEventListener('click', (e) => { var item = document.createElement('div') item.id = `item ${main.querySelectorAll('*').length}` item.innerHTML = item.id main.appendChild(item) }) document.getElementById('remove').addEventListener('click', (e) => { var items = main.querySelectorAll('*') items.length > 0 && main.removeChild(items[items.length - 1]) }) </script> |
Aetae, и всем, большое спасибо. insertAdjacentHTML() - должен отлично подойти.
Пойду применять. |
Часовой пояс GMT +3, время: 01:10. |