追加元素并删除它会破坏jquery中的所有事件处理程序?

时间:2015-04-05 20:38:52

标签: javascript jquery

好的我创建元素,分配点击处理程序,并将其附加到正文。然后我删除它并重新加载它并单击处理程序不再工作???

为什么会发生这种情况。

var btn = $('<button>').text('hi').click(function(){console.log(3);});
var div = $('<div>');
div.append(btn);
$('body').append(div);
//click it now, it works..
div.html('');
div.append(btn);
// now button doesn't work..

那么为什么会发生这种情况,我该怎么做才能解决它。

4 个答案:

答案 0 :(得分:7)

由于.html('').empty()基本相同,因此以下情况适用(来自jQuery docs):

  

为了避免内存泄漏,jQuery会在删除元素本身之前从子元素中删除其他构造(如数据和事件处理程序)。

     

如果要删除元素而不破坏其数据或事件处理程序(以便以后可以重新添加),请改用.detach()

一种选择是使用event delegation。在这样做时,事件不直接绑定到button元素,它被绑定到一个不被删除的常量父元素。

Example Here

$(document).on('click', 'button', function () {
    // ..
});

如上所述,另一种选择是使用.detach() method从DOM中删除元素,而不删除附加的事件侦听器。

  

.detach() method.remove()相同,只是.detach()会保留与已删除元素关联的所有jQuery数据。当删除的元素稍后要重新插入DOM时,此方法很有用。

Example Here

div.find('button').detach();
div.append(btn);

答案 1 :(得分:2)

在第二个div.append(btn)之后放这个; - &gt; btn = $('button').text('hi').click(function(){console.log(3);});

答案 2 :(得分:2)

这是因为您在包含该按钮的DIV上调用了html()

当您使用空字符串调用html()时,它会在内部调用empty() 在元素上调用empty()会迭代该元素中的所有元素,从而安全地删除所有数据和事件。

通过调用按钮上的jQuery.cleanData来执行此操作,该按钮再次显式调用jQuery.removeEvent,删除按钮上的所有事件。

该按钮仍然存储在变量btn中,因此可以再次追加,但由于父元素已调用html(""),因此它已丢失所有数据和附加到其上的任何事件。

解决方案是使用detach()删除所有数据和事件完整的元素,以便可以再次追加,或者您可以将事件附加到未被删除的父元素,或者你可以隐藏元素,通常没有理由删除元素只是为了重新加载它,隐藏它更好。

FIDDLE

答案 3 :(得分:2)

这是非常有趣的情况。使用div方法清除html('')后会发生什么。看看source code,你会看到内部jQuery调用jQuery.cleanData(getAll(elem, false));。此方法负责删除已删除的所有子元素的所有相关data。这对于避免内存泄漏很重要。

清除数据还会删除与on(和类似)方法绑定的事件,因为这些事件处理程序也存储在内部缓存对象中。

结果,即使您删除了div的内容,btn对象仍然在内存中,但之前绑定到它的事件已经消失。

这是对问题的解释。解决方案是使用名为detach的专用方法。它将从DOM中删除按钮,但会保留事件数据,以便以后再次附加元素。

// remove element but keep its data
btn.detach();

// append back
div.append(btn);

在这种情况下,您不应使用html('')