2

如果我有以下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');
});

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

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

4

4 回答 4

5

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

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

这里的教训是 ajax 加载的脚本会被解析,所以如果你有处理程序,它们就会被附加

于 2012-06-20T21:48:45.070 回答
3

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

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

否则显然将其放在其他地方。

于 2012-06-20T21:50:16.180 回答
1

正如已经说过的,main.js 会在您每次执行.load().

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

  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()在每个对象上使用来设置您已经安装了给定事件处理程序的标志。

于 2012-06-20T22:05:30.250 回答
1

I suppose you placed that script into the reloaded content and not within the head section, where all scripts usually reside, because event handler becomes detached from the #main_content each time it's reloaded? Well, there's another way:

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

You can place, load and execute this code just once - and won't need to reattach the event each time the block in question is reloaded.

Take note, though, that body in my code is better be replaced with a more specific element - in a perfect world, direct parent of #main_content element.

UPDATE: this is so called event delegation, and it's very well described in the .on docpage. In the previous versions of jQuery, you had to use either .live or .delegate methods.

于 2012-06-20T21:55:23.880 回答