Javascript: обработка событий с несколькими динамическими элементами
Я ищу лучший способ обработки событий для нескольких элементов на странице, которые могут отображаться динамически. В настоящее время я использую этот код:
var myToolbar = document.createElement('div');
setInterval(function () {
for (let textField of document.querySelectorAll('textarea[name="text"]:not(.modified)')) {
textField.classList.add('modified');
textField.addEventListener('focus', function () {
textField.insertAdjacentElement('beforebegin', myToolbar);
});
}
}, 1000);
Это прекрасно справляется с моей задачей, но наличие интервала, работающего все время, кажется неуклюжим.
2 ответа:
Вы можете использовать MutationObserver. Пример:
setInterval(() => { const allDivs = document.querySelectorAll('div'); const randomDiv = allDivs[Math.floor(Math.random() * allDivs.length)]; randomDiv.appendChild(document.createElement('div')); }, 1000); const obs = new MutationObserver(track); obs.observe(document.body.children[0], { childList: true, subtree: true }); function track(mutations) { mutations.forEach((mutation) => { mutation.addedNodes.forEach(addedNode => { if (addedNode.tagName === 'DIV') addedNode.classList.add('found'); }); }); }
div { border: 1px solid black; background-color: white; height: 20px; width: 20px; } .found { background-color: yellow; }
<div> </div>
Для вашего конкретного случая вы хотите найти новые
textarea[name="text"]
s, поэтому вместо этого вы должны проверить:if (addedNode.tagName === 'TEXTAREA' && addedNode.name === 'text') { // ... }
Вы должны знать о компонентах, которые вы визуализируете на веб-странице, и их состоянии в вашем приложении. Если это не так, то ваш шаблон дизайна ошибочен и нуждается в более тщательном обдумывании. То, что вы сейчас делаете, - это путь к катастрофе. Добавление слушателей событий волей-неволей внутри
setInterval
, даже не очищая их - пахнет утечкой памяти.Компоненты, которые вы изначально визуализируете на веб-странице, вероятно, должны иметь собственные прослушиватели событий для обработки того, что вы называете появление "динамических" элементов. Эти динамические элементы появляются либо из-за того, что ваше приложение помещает их туда, либо пользователь делает что-то, чтобы они появились там. Обе эти вещи можно отслеживать и поддерживать в состоянии приложения.
С учетом сказанного, чтобы избежать даже описанной проблемы, вам нужно инвертировать управление состоянием вашего приложения в ваш код, а не в состояние DOM. Это позволит сделать настройку слушателей событий и удаление прослушивателей событий, когда это требуется, намного проще.
Таким образом, если вы не делаете что-то необычное с ContentEditable регионами, вам следует пересмотреть дизайн вашего приложения.