由动态生成的元素触发的事件不会被事件处理程序捕获

Posted

技术标签:

【中文标题】由动态生成的元素触发的事件不会被事件处理程序捕获【英文标题】:Events triggered by dynamically generated element are not captured by event handler 【发布时间】:2012-10-01 13:13:39 【问题描述】:

我有一个<div>id="modal" 使用jQuery load() 方法动态生成:

$('#modal').load('handlers/word.edit.php');

word.edit.php 包含一些输入元素,它们被加载到模态<div>

使用 jQuery 的 keyup 方法我可以在事件触发后捕获输入值,但是 当元素被动态添加到模态 div 时,当用户输入他们的文本时不再触发该事件。

哪种 jQuery 方法支持处理由动态创建的元素触发的事件?

创建新输入元素的代码是:

$('#add').click(function() 
    $('<input id="'+i+'" type="text" name="translations' + i + '"  />')
      .appendTo('#modal');

获取用户值的代码为:

$('input').keyup(function() 
    handler = $(this).val();
    name = $(this).attr('name');

第二个代码块似乎适用于原始元素,但不会被新的动态生成的元素触发。

【问题讨论】:

我还在我的 index.php &lt;script src="js/jquery-1.6.2.min.js"&gt;&lt;/script&gt; &lt;script src="js/jquery-ui-1.8.18.min.js"&gt;&lt;/script&gt; 上加载了两个版本的 jQuery,但不能使用函数 on 只能使用函数 live edit: #modal to input $('input').live('keyup', 'input', function() handler = $(this).val(); name = $(this).attr('name'); alert(handler+" "+name); ); 当我使用代码时它工作正常,再次感谢您的帮助:) 只是一个注释。您不加载两个版本的 JQuery。您加载了 1.6.2 版的 JQuery 和 1.8.18 版的 JQuery UI。 JQuery UI 用于用户界面组件,与 JQuery 不同。为了获得最佳实践,请尝试使用来自 Google 等在线资源的 JQuery 而不是本地文件。 @Carlos Eduardo Bruno Pereira 感谢您的清理,我一直认为两者都具有相同的包,仅存在 -ui 并添加了额外功能,但事实并非如此 :) Event binding on dynamically created elements? 的可能重复项 【参考方案1】:

您需要delegate the event 到页面内最近的静态祖先元素(另请参阅"Understanding Event Delegation")。这只是意味着,您绑定事件处理程序的元素必须在绑定处理程序时已经存在,因此对于动态生成的元素,您必须允许事件冒泡并进一步处理它。

jQuery .on 方法是执行此操作的方法(或 .delegate 用于旧版本的 jQuery。)

// If version 1.7 or above

$('#modal').on('keyup', 'input', function() 
    handler = $(this).val();
    name = $(this).attr('name');
);

或者在旧版本中

// If version 1.6 or below

// note the selector and event are in a different order than above
$('#modal').delegate('input', 'keyup', function()

    handler = $(this).val();
    name = $(this).attr('name');
);

【讨论】:

您的回答、您链接到的文章以及@ernie 提到的&lt;parentSelector&gt; 都确实帮助我理解了.on() 的工作原理。谢谢! 非常有帮助的答案,非常感谢您提供的信息【参考方案2】:

发生这种情况是因为您在连接事件之后添加了输入元素。试试.on:

$('body').on('keyup', 'input', function() 
    handler = $(this).val();
    name = $(this).attr('name');
);

使用.on 将确保keyup 事件连接到页面上最初的输入,以及以后动态添加的任何输入。

【讨论】:

对不起,之前是在 modal div 中的 appendTo() 之前加载的工作输入,但现在两者都不起作用,我不明白有什么不同on 使用并且我认为输入元素在 modal div 中而不是在 body 但每个 div 必须在 body 我中创建不知道,但它不起作用 您可以将'body' 更改为您喜欢的任何选择器。不过,该选择器应该可以工作。您的模态 html 仍将在正文内,因为它不能在正文外。【参考方案3】:

当您动态更改 DOM 时,jQuery 不会将事件处理程序附加到它们。你需要使用on() and delegated events

对于您的输入项,您需要以下内容:

$("<parentSelector>").on("keyup", "input", function()  
    handler = $(this).val();
    name = $(this).attr('name');
)

其中 parentSelector 在 DOM 中比输入元素更高,并且是在页面加载时存在的元素,可能是表单 ID 或其他东西。

【讨论】:

你的最后一句话真的帮助我理解了这个概念。谢谢!【参考方案4】:

功能绑定是在页面加载中进行的。使用函数 live() 处理动态创建的元素。示例:

$ ("p"). live ("click", function () 
    // Your function
);

【讨论】:

就像一个注释一样,.live() 在 jQuery 1.7 中已被弃用,所以最好切换到 .on()【参考方案5】:

如果您需要捕获所有表单元素的更改,尤其是选择框,我知道这里没有提到它们,但了解一下会有所帮助,请使用以下代码:

$(document).on('change', ':input', function () 
   alert('value of ' + $(this).attr('name') + ' changed')
);

这应该涵盖所有inputtextareaselectcheckboxradio

【讨论】:

以上是关于由动态生成的元素触发的事件不会被事件处理程序捕获的主要内容,如果未能解决你的问题,请参考以下文章

DOM事件探秘

如何在 MFC 应用程序中捕获 OLE 控件事件?由创建的 ActiveX 控件触发

事件处理

JavaScript-计算器

Js事件处理模型/周期

浅谈浏览器的事件冒泡机制