好的我创建元素,分配点击处理程序,并将其附加到正文。然后我删除它并重新加载它并单击处理程序不再工作???
为什么会发生这种情况。
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..
那么为什么会发生这种情况,我该怎么做才能解决它。
答案 0 :(得分:7)
由于.html('')
与.empty()
基本相同,因此以下情况适用(来自jQuery docs):
为了避免内存泄漏,jQuery会在删除元素本身之前从子元素中删除其他构造(如数据和事件处理程序)。
如果要删除元素而不破坏其数据或事件处理程序(以便以后可以重新添加),请改用
.detach()
。
一种选择是使用event delegation。在这样做时,事件不直接绑定到button
元素,它被绑定到一个不被删除的常量父元素。
$(document).on('click', 'button', function () {
// ..
});
如上所述,另一种选择是使用.detach()
method从DOM中删除元素,而不删除附加的事件侦听器。
.detach()
method与.remove()
相同,只是.detach()
会保留与已删除元素关联的所有jQuery数据。当删除的元素稍后要重新插入DOM时,此方法很有用。
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()
删除所有数据和事件完整的元素,以便可以再次追加,或者您可以将事件附加到未被删除的父元素,或者你可以隐藏元素,通常没有理由删除元素只是为了重新加载它,隐藏它更好。
答案 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('')
。