jQuery替代html而不破坏事件监听器

时间:2017-04-18 16:50:56

标签: javascript jquery dom dom-manipulation

在我的代码的某一点上,我需要从AJAX请求中获取一个html字符串并用它替换某个容器。

我有这个,但正如在网上的几个引用中所述,它是垃圾收集并取消绑定事件监听器

this.rightPanel.innerHTML = content;

然而,jQuery .html()函数不会发生这种情况,这会使事件监听器保持工作,所以这样做

$(this.rightPanel).html(content);

没有缺陷。

我不想将jQuery用于DOM操作,即使浏览器本身支持它也是如此。我必须重现与jQuery .html()相同的行为的最佳选择是什么?

谢谢

1 个答案:

答案 0 :(得分:2)

  

但是,jQuery .html()函数...

不会发生这种情况

是的,确实如此。

  

...让事件监听器保持工作......

不,它没有。 : - )

Like-for-like,他们对事件监听器做同样的事情:

// DOM
document.getElementById("btn1").addEventListener("click", function() {
  console.log("Button 1");
});

// jQuery
$("#btn2").on("click", function() {
  console.log("Button 2");
});

// Replace 'em
$("#btnRep").on("click", function() {
  var wrap1 = document.getElementById("wrap1");
  wrap1.innerHTML = wrap1.innerHTML + " (replaced)";
  var wrap2 = $("#wrap2");
  wrap2.html(wrap2.html() + " (replaced)");
});
<p>Click Button 1, then Button 2, Then Replace, then Buttons 1 and 2 again -- you'll see *neither* of them has a handler anymore after being replaced.</p>
<div id="wrap1">
  <input type="button" id="btn1" value="Button 1">
</div>
<div id="wrap2">
  <input type="button" id="btn2" value="Button 2">
</div>
<input type="button" id="btnRep" value="Replace">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

您可能已经看到jQuery使事件委派真的非常容易:这就是您将事件挂钩到祖先元素(甚至可能是body)的地方,但是你请求jQuery仅在冒泡期间通过元素时触发您的处理程序。这样,您可以替换后代元素,因为事件侦听器不在它们上面,它位于容器/祖先上。

你也可以在没有jQuery的情况下做到这一点,这只是更多的工作:

function addDelegated(element, eventName, selector, handler) {
  element.addEventListener(eventName, function(e) {
    // Start with the target element, and go through its parents
    // until we reach the element we hooked the event on (`this`)
    var element = e.target;
    while (element && element !== this) {
        // `matches` test the element against a CSS selector
        if (element.matches(selector)) {
          // Yes, trigger the handler
          return handler.call(element, e);
        }
        element = element.parentNode;
    }
  });
}

// Hook the event on wrap1
addDelegated(document.getElementById("wrap1"), "click", "#btn1", function() {
  console.log("Button 1");
});

// Replace
document.getElementById("btnRep").addEventListener("click", function() {
  var wrap1 = document.getElementById("wrap1");
  wrap1.innerHTML = wrap1.innerHTML + " (replaced)";
});
<p>Click Button 1, then Replace, then Button 1 again.</p>
<div id="wrap1">
  <input type="button" id="btn1" value="Button 1">
</div>
<input type="button" id="btnRep" value="Replace">