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, время: 21:27. |