我正在尝试创建一个供我自己使用的 jQuery 插件,该插件可用于使用单个命令设置 jQuery 移动对话框的处理程序,例如:$('#dialog').setup_dialog({ callback:回调函数});
但是,由于其中的闭包,我的处理程序有相当明显的内存泄漏:
$.fn.setup_dialog = function( options ) {
var settings = $.extend({
callback : 0
}, options);
var that = this;
return this.live('pagebeforeshow', function(event, ui) {
console.log("outside");
$('form', that).submit( function(e) {
var $inputs = $('form :input', that); // get all form inputs
var values = {};
$inputs.each(function() {
values[this.name] = $(this).val();
});
that.dialog('close');
if ( settings.callback && typeof(settings.callback) === "function" ) {
$('#'+ui.prevPage[0].id).live('pagebeforeshow', function() {
settings.callback(values, that);
console.log("inside");
});
}
return e.preventDefault();
});
});
}; /* setup_dialog */
如果你运行上面的代码,你会看到“inside”和“outside”先打印一次,然后打印三次(一次提交两次),然后六次(一次提交三次),等等。
该代码的目的是在 jQuery Mobile 对话框出现时将事件处理程序附加到它将捕获表单提交,收集所有表单值,然后将它们传递给将修改原始页面的回调函数(启动对话框)。
请注意,由于 jQuery Mobile 使用 AJAX 在页面之间切换的方式,我需要使用 .live 来绑定(bind)事件(.bind 或 .one 不起作用)。
我有什么想法可以避免事件累积(并且可能还稍微清理一下代码)吗?
最佳答案
您正在将事件处理程序绑定(bind)到其他事件处理程序中。并且外部事件处理程序不是唯一事件(它们不止一次发生),这意味着您的内部事件处理程序被绑定(bind)了不止一次。
一个好的修复方法是从 pagebeforeshow
事件处理程序中删除 submit
事件处理程序,并将其放在 pagecreate
或 pageinit
事件处理程序(这些是唯一的,每个对话框只运行一次)。
如果您想保留当前的逻辑,那么您可以在事件处理程序运行时解除绑定(bind),这样您就不会堆叠多个执行相同操作的事件处理程序:
$.fn.setup_dialog = function( options ) {
var settings = $.extend({
callback : 0
}, options);
var that = this;
return this.live('pagebeforeshow', function(event, ui) {
console.log("outside");
$('form', that).submit( function(e) {
var $inputs = $('form :input', that); // get all form inputs
var values = {};
$inputs.each(function() {
values[this.name] = $(this).val();
});
that.dialog('close');
if ( settings.callback && typeof(settings.callback) === "function" ) {
$('#'+ui.prevPage[0].id).live('pagebeforeshow', function() {
settings.callback(values, that);
console.log("inside");
$(this).die('pagebeforeshow');//NEW, unbind the pagebeforeshow event handler for this element
//since it will be bound the next time the dialog is shown anyway
});
}
$(this).die('submit');//NEW, unbind the submit event handler for this form
//since it will be bound the next time the dialog is shown anyway
return e.preventDefault();
});
});
}; /* setup_dialog */
这是 .die()
的文档:http://api.jquery.com/die/
关于javascript - 避免闭包引起的 jQuery Mobile 内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8993101/