[英]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都会被重新分析并重新运行。
你有几个选择来解决这个问题:
.load()
时都不会对其进行重新分析和运行。 这些是按照实施简单的顺序呈现的。
对于选项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.