Я пробовал
node.cloneNode(true); // deep copy
Кажется, он не копирует прослушиватели событий, которые я добавил с помощью node.addEventListener("click", someFunc);
.
Мы используем библиотеку Dojo.
Я пробовал
node.cloneNode(true); // deep copy
Кажется, он не копирует прослушиватели событий, которые я добавил с помощью node.addEventListener("click", someFunc);
.
Мы используем библиотеку Dojo.
cloneNode()
не копирует прослушиватели событий. На самом деле, нет способа получить прослушиватели событий через DOM после их подключения, поэтому ваши варианты:
Node.addEventListener()
, чтобы отслеживать слушателей, добавленных к каждому node. Например, метод jQuery clone()
может скопировать node с его прослушивателями событий.Пример делегирования события.
Прочитав ответ Тима Дауна, я обнаружил, что делегированные события очень легко реализовать, решая аналогичную проблему, с которой я столкнулся. Я думал, что добавлю конкретный пример, хотя это в JQuery, а не в Dojo.
Я пересматриваю приложение в семантическом интерфейсе, которому требуется небольшой фрагмент JS, чтобы кнопки закрытия сообщений работали. Однако сообщения клонируются из тега шаблона HTML с использованием document.importNode
в библиотеке. Это означало, что даже если я прикреплю обработчики событий к шаблону в новом HTML, они будут потеряны во время клонирования.
Я не могу сделать Тим вариант 1, просто повторно присоединить их во время клонирования, так как библиотека сообщений не зависит от инфраструктуры интерфейса. (Интересно, что мой предыдущий интерфейс был в Zurb Foundation, который использует атрибут "закрываемость данных", функциональность которого действительно выживает в процессе клонирования).
Предложенная обычная обработка событий была такой:
$('.message .close').on('click', function() {
$(this)
.closest('.message')
.transition('fade');
});
Проблема заключается в том, что ".message" при загрузке приложения соответствует только одному шаблону, а не фактическим сообщениям, которые приходят позже через веб-сокеты.
Делать это делегированным, означало присоединение события к контейнеру, в который клонируются сообщения <div id="user-messages">
Так и становится:
$('#user-messages').on('click', '.message .close', function() {
$(this)
.closest('.message')
.transition('fade');
});
Это сработало сразу, сохранив любую сложную работу, например, третий вариант переноса событий.
Эквивалент Dojo выглядит довольно схожим по концепции.
Это не дает точного ответа на вопрос, но если вариант использования позволяет перемещать элемент, а не копировать его, вы можете использовать removeChild вместе с appendChild, который сохранит прослушиватели событий. Например:
function relocateElementBySelector(elementSelector, destSelector) {
let element = document.querySelector(elementSelector);
let elementParent = element.parentElement;
let destElement = document.querySelector(destSelector);
elementParent.removeChild(element);
destElement.appendChild(element);
}