jQuery 自动将事件处理程序注册到通过 Ajax 响应添加到 DOM 的元素上的用户操作
Posted
技术标签:
【中文标题】jQuery 自动将事件处理程序注册到通过 Ajax 响应添加到 DOM 的元素上的用户操作【英文标题】:jQuery automatically register event handler(s) to user actions on elements that are added to DOM by Ajax response 【发布时间】:2012-09-12 06:27:49 【问题描述】:对于具有许多屏幕和导航的 ajax Web 应用程序,要为 div 或链接或按钮附加事件处理程序,我们可以编写如下代码:
//Using $.on inside Ajax success handler
$("#container").on("click", "#selector", function(event)
);
如果容器在 DOM 中不存在,此方法将不起作用。要使其工作,必须使用文档或正文作为容器,性能可能不好。
Ajax 成功处理程序中可能有很多行代码。为了更好地组织,可以将代码移动到一个函数并在 Ajax 成功处理程序中调用该函数。但是我们必须为所有排列和组合创建许多注册事件函数。
注册函数代码混乱。
如果事件处理程序已经注册,再次注册将导致两个偶数处理程序。所以我们必须取消注册并注册(或仅在尚未附加的情况下附加)-不确定性能问题。
还有其他选择吗?
我正在考虑以下内容:
在一个位置为模块维护容器、目标和单击事件处理程序的映射。在 ajaxComplete 全局事件处理程序中,如果 xhr.responsehtml 有容器,则将事件处理程序附加到目标元素(仅在尚未附加时附加)。
$(document).ajaxComplete(function(e, xhr, settings)
for(ind in clickEventListeners)eventlistner = clickEventListeners[ind];
if($(eventlistner.container,xhr.responseHTML).length > 0)
$(eventlistner.target).on("click",function()
eventlistner.processor(this);
);
);
优点:所有事件处理程序都记录在一个模块的一个地方。每个 ajax 成功处理程序都没有代码混乱。
缺点:我不确定是否有。
如果有什么建议请指教。
【问题讨论】:
【参考方案1】:更新
将事件绑定到将动态添加的元素需要将侦听器放置在文档上,而不是 1.9+ 版本的元素上。从 Jquerys api 你可以找到这一行:
“事件处理程序仅绑定到当前选定的元素;它们必须在您的代码调用 .on() 时存在于页面上。”
因此,将事件绑定到文档并在之后放置选择器将允许实际识别此侦听器。
$(document).delegate( "#selector", "click",
或
$(document).on( "click", "#selector",
示例:http://jsfiddle.net/2HA7d/
在以前的 Jquery 版本中,可以使用 live() 函数,它实际上将侦听器放置到文档中,从而可以完全按照您的想法运行:
$("#selector").live("click",
示例:http://jsfiddle.net/q3jYB/
第二个例子的功能与第一个例子相同。
由于该元素尚不存在,javascript 无法为您要查找的元素添加事件侦听器。因此,当尝试为动态添加的元素添加侦听器并且您使用较新的 jquery 版本(1.9+)并使用 on() 或 delegate() 时,请将事件侦听器添加到文档中,如提供的第一个 Fiddle 所示。
编辑:
正如我在 cmets 中所说,如果可能,将事件侦听器添加到容器中也是一个非常可行的选择,并且可能会提高性能
来源:
https://api.jquery.com/on/
http://jquery.com/upgrade-guide/1.9/
How does jQuery .live() work?
希望这会有所帮助。
【讨论】:
更新响应以提供更多解释 很好的答案和很好的参考链接。 +1 $("#container").delegate( "#selector", "click"... 应该会提高性能。因为更少的事件会冒泡到#container,并且必须执行的检查更少.【参考方案2】:我和你的情况类似,试试这个,这对我来说效果很好!
首先在主文件中我像这样绑定事件处理程序:
$('body').bind( 'gridloaded', function(e,f) my logic );
在最后动态填充我的 DOM 树的 ajax 文件中,我在需要的地方添加触发器和我所在的元素 ID,如下所示:
$('body').trigger('gridloaded', $(this).attr('id') );
onClickButton: function()
$("body").trigger("gridloaded", $(this).attr('id'))
我喜欢这种方法,因为它很简洁:无论 ajax 调用需要多长时间,它总是会在正确的时间只触发一个事件。
【讨论】:
【参考方案3】:如果事件处理程序已经存在于 DOM 中,那么将事件处理程序绑定到 document
或 body
可能不是一个好主意。
但如果元素是动态生成的(如您的情况),那么您可能会将事件绑定到文档,然后维护您自己的容器、目标和单击事件处理程序堆栈,例如:
$(document).on("click", "#selector", function () )
来源: Are there any drawbacks to listen events on document level in jQuery?
【讨论】:
以上是关于jQuery 自动将事件处理程序注册到通过 Ajax 响应添加到 DOM 的元素上的用户操作的主要内容,如果未能解决你的问题,请参考以下文章