将事件附加到动态生成的HTML

Attaching events to dynamically-generated HTML?

本文关键字:HTML 动态 事件      更新时间:2023-09-26

将静态html表转换为JavaScript生成的表时遇到问题。以前,我的js/jQuery代码在表中的数据元素上设置了点击处理程序,如下所示:

$(function() {
   $('my_table td').click(function(e) {
   ...handler code
});

这很好,但我不得不更改我的表,以便在JavaScript:中动态生成内容

// 'table_contents' is "<table><tbody>...</tbody></table>"
$('#my_table').html(table_contents);

当我这样做时,我会丢失单击处理程序。我想这并不奇怪,因为我只是删除了旧的html并用新的html替换它。然而,我不知道如何正确处理这个问题。我可以给我的匿名函数一个名称,并在更改html时调用它吗?还是必须做其他事情,比如向每个新的td元素显式添加一个事件侦听器?在替换旧的html之后,我是否必须做任何事情来清理,比如释放旧的处理程序/侦听器?js是否存在必须手动修复的内存/资源泄漏?

编辑

很抱歉对此感到愚蠢,但我无法让建议的on/delete解决方案发挥作用。我的测试html是:

<div id="date_test">
<table><tbody><td>42</td></tbody></table>
</div>

我试着用三种不同的方式回应点击td'42':

$("#date_test").on("click", "td", function() {
   alert($(this).text());
});
$('#date_test').delegate('td', 'click', function() {
   alert($(this).text());
});
$(function() {
   $('#date_test td').click(function() {
      alert($(this).text());
   })
})

其中,只有第三个有效。请注意,这完全是静态代码;这是3个不同的精简测试用例。对于前两种情况,代码从不执行;我可以输入语法错误而不是警报,这没有什么区别。知道我做错了什么吗?我在jQuery 1.7上。

您可以使用on方法将事件处理程序委托给祖先元素。假设此时DOM中存在#my_table,则执行以下代码:

$("#my_table").on("click", "td", function() {
    //Do stuff
});

on方法仅在jQuery 1.7+中可用。如果您使用的是旧版本,则可以使用delegate

这之所以有效,是因为DOM事件是从它们通过DOM产生的元素开始的。事件在祖先上捕获,如果起源与选择器匹配,则触发事件处理程序。

这不仅提供了处理源自最初不属于DOM的元素的事件的好处,还可以提高性能,因为它需要更少的事件处理程序(如果将事件处理程序绑定到每个td,并且有很多td元素,那么就有很多事件处理程序-使用事件委派意味着只有一个)。

更新(请参阅问题编辑)

第三个示例之所以有效,是因为您已经将代码封装在ready事件处理程序中。$(function() { ... });$(document).ready(function() { ... });的简写。

这是必要的,因为否则要将事件处理程序绑定到的#date_test元素将不存在于DOM中。如果您正在执行任何DOM操作,请始终将代码放在就绪的事件处理程序中。

您可以将on版本或delegate版本放在就绪事件处理程序函数中,它应该可以工作。

我最近遇到了同样的问题。事实证明,JS加载后进入页面的元素不会附带事件。我通过使用委派很容易地解决了这个问题http://api.jquery.com/delegate/.它通过父元素向上传播事件,直到它们被捕获并执行为止。诀窍是确保将事件委托给一个元素,该元素在第一次加载js时始终存在,因此添加到该容器中的任何新元素都将捕获其事件。

$('#container').delegate('#my_table td', 'click' (function(e) {...

根据您使用的jquery版本,您可以尝试使用jquery.on()

http://api.jquery.com/on/

如果你使用的是旧版本,那么.delete()将为你工作:

http://api.jquery.com/delegate/

您可以使用on()方法http://api.jquery.com/on/

$("#my_table td").on("click", function(event){
    alert($(this).text());
});