如何使用事件侦听器复制DOM节点?

时间:2013-03-14 11:48:10

标签: javascript dom dojo

我试过

node.cloneNode(true); // deep copy

似乎没有复制我使用node.addEventListener("click", someFunc);添加的事件侦听器。

我们使用Dojo库。

4 个答案:

答案 0 :(得分:60)

cloneNode()不会复制事件侦听器。实际上,一旦附加了DOM,就无法通过DOM获取事件监听器,因此您可以选择:

  • 手动将所有事件侦听器添加到克隆节点
  • 重构您的代码以使用事件委派,以便所有事件处理程序都附加到包含原始和克隆的节点
  • Node.addEventListener()周围使用包装函数来跟踪添加到每个节点的侦听器。例如,这就是jQuery的clone()方法能够使用其事件侦听器复制节点的方式。

答案 1 :(得分:1)

事件委托示例。

在阅读Tim Down的答案后,我发现委托事件非常容易实现,解决了我遇到的类似问题。我以为我会添加一个具体的示例,尽管它在JQuery中而不是Dojo中。

我正在重新整理语义UI中的应用程序,它需要一小段JS才能使消息关闭按钮起作用。但是,消息是使用库中的document.importNode从HTML模板标记克隆的。这意味着即使我确实将事件处理程序附加到新HTML中的模板上,在克隆过程中它们也会丢失。

我无法执行Tim的选项1,因为消息传递库与前端框架无关,因此在克隆过程中它们只是简单地重新连接它们。 (有趣的是,我以前的前端是在Zurb Foundation中,它使用“数据可关闭”属性,该功能在克隆过程中仍然存在。)

normal event handling suggested was like this

$('.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 equivalent在概念上看起来非常相似。

答案 2 :(得分:0)

这不能完全回答问题,但是如果用例允许移动元素而不是复制元素,则可以将removeChildappendChild将保留事件监听器。例如:

function relocateElementBySelector(elementSelector, destSelector) {
  let element = document.querySelector(elementSelector);
  let elementParent = element.parentElement;
  let destElement = document.querySelector(destSelector);
  elementParent.removeChild(element);
  destElement.appendChild(element);
}

答案 3 :(得分:0)

这是@JeromeJ在评论中描述的内容。使用此HTML代码创建初始元素。

<DIV ONCLICK="doSomething(this)">touch me</DIV>

克隆此元素时,结果将具有相同的处理程序,并且“ this”将指向克隆的元素。

如果可以在JavaScript中轻松添加ONCLICK处理函数,那就太好了。这种方法意味着您必须用HTML编写一些代码。