繁体   English   中英

如何在动态加载的脚本中使用jQuery on()

[英]how to use jQuery on() in dynamically loaded scripts

如果我有以下html:

<html>
   <div id="main_content">
      <button>click me</button>
      <script src="main.js" ></script>
   </div>
</html>

和main.js:

$('#main_content').on('click', 'button', function() {
    console.log('you clicked');
});

如果我执行整页加载,则单击该按钮仅注册一个控制台消息。 但是,如果我随后通过AJAX请求重新加载main_content's内容,则每次单击按钮都会发出2条控制台消息。 它将为每个后续的AJAX加载提供3,4,5 ...消息,但总是一个用于整页重新加载。

有人可以解释这种行为并提出可行的解决方案吗?

那是因为你正在加载main.js的多个副本,因此每次都要附加一个事件处理程序。
每次加载<script>都会附加一个处理程序

 <button>click me</button>
  <script src="main.js" ></script>

这里的教训是解析由ajax加载的脚本,因此如果你在其中有处理程序,它们就会被附加

如果您确实需要一直重新加载该脚本,请在其中执行此操作:

$('#main_content').off("click").on('click', 'button', function() {
    console.log('you clicked');
});

否则显然是把它放在其他地方。

我假设您将该脚本放入重新加载的内容中,而不是放在所有脚本通常驻留的head部分中,因为事件处理程序每​​次重新加载时都会从#main_content分离出来? 那么,还有另一种方式:

$(function(){
   ...
   $('body').on('click', '#main_content', function() { console.log('You clicked!'); });
});

您可以只放置,加载和执行此代码一次 - 并且每次重新加载有问题的块时都不需要重新附加事件。

但请注意,我的代码中的body最好用更具体的元素替换 - 在完美的世界中, #main_content元素的直接父元素。

更新:这就是所谓的事件委托 ,它在.on docpage中有很好的描述。 在以前版本的jQuery中,您必须使用.live.delegate方法。

正如已经说过的那样,每次执行.load()时,main.js都会被重新分析并重新运行。

你有几个选择来解决这个问题:

  1. 将main.js移动到动态加载的内容之外,以便每次执行.load()时都不会对其进行重新分析和运行。
  2. 修改main.js,使整个脚本只执行一次。
  3. 修改main.js以了解多次加载,以防止重复安装相同的事件处理程序。

这些是按照实施简单的顺序呈现的。

对于选项2,您可以将所有main.js放在if语句中,以便它只执行一次:

if (!window.__main__js__defined) {
    window.__main__js__defined = true;

   // rest of main.js code here

}

对于选项3,您必须保护您希望反重复保护的每个单独的事件处理程序,可能在每个对象上使用.data()来设置您已经安装了给定事件处理程序的标志。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM