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 中,那么将事件处理程序绑定到 documentbody 可能不是一个好主意。

但如果元素是动态生成的(如您的情况),那么您可能会将事件绑定到文档,然后维护您自己的容器、目标和单击事件处理程序堆栈,例如:

$(document).on("click", "#selector", function () )

来源: Are there any drawbacks to listen events on document level in jQuery?

【讨论】:

以上是关于jQuery 自动将事件处理程序注册到通过 Ajax 响应添加到 DOM 的元素上的用户操作的主要内容,如果未能解决你的问题,请参考以下文章

jQuery事件

jquery 事件,注册 与重复事件处理

jQuery:将 $(this) 传递给命名函数事件处理程序

C#里事件和委托有啥区别啊??

如何将事件处理程序绑定到 jQuery 中的实例?

使用 JQuery 将事件处理程序添加到 iframe