JQuery Dialog的內(nèi)存泄露問題解決方法
更新時(shí)間:2010年06月18日 23:50:30 作者:
如何避免JQuery Dialog的內(nèi)存泄露,需要的朋友可以參考下。
對于頁面來說,JQuery中的Dialog從效果上來說還可以,而且使用簡單,只要短短幾行綁定的代碼就可以實(shí)現(xiàn)彈出效果。
代碼
$('#dialog').dialog({
autoOpen: false,
width: 600,
buttons: {
"Ok": function() {
$(this).dialog("close");
},
"Cancel": function() {
$(this).dialog("close");
}
}
});
在一些JS交互性不多的一般頁面來說,沒有任何問題!但是對于交互性強(qiáng)的,需要動態(tài)加載與釋放DOM的頁面來說,它就是一個(gè)悲劇的東西!為什么這樣說?大家看下下面的例子:
一段簡單的代碼,一個(gè)DIV是通過動態(tài)加載到頁面上,然后對該DIV用Dialog進(jìn)行綁定,以達(dá)到彈出的目的!下面的test元素就是<div id="test"></div>。
代碼
function TestAppend() {
$("#test").append('<div id="dialog"><div id="fileQueue"></div> <input type="file" name="uploadify" id="uploadify" />' +
'<a href="javascript:upload();">上傳</a>' +
'<a href="javascript:$(#uploadify).uploadifyClearQueue()">取消上傳</a><div>');
$('#dialog').dialog({
autoOpen: false,
width: 600,
buttons: {
"Ok": function() {
$(this).dialog("close");
},
"Cancel": function() {
$(this).dialog("close");
}
}
});
return false;
}
接著,我需要刪除該DOM元素,一般來說,正常的做法都是$("#test").empty();這行簡單的代碼就完成了!這樣有效嗎?!當(dāng)執(zhí)行完這樣代碼后,你再用$('#dialog')來獲取dialog元素,郁悶的事情發(fā)生了,既然獲取到了!為什么!不是已經(jīng)empty了嗎!
下面我們來看下這一悲劇是如何造成的,
我們把注意點(diǎn)放到$('#dialog').dialog上面,然后看看JQuery的實(shí)現(xiàn)代碼是如何寫的,當(dāng)我們跟蹤代碼到dialog類中的_create方法的時(shí)候,問題的原因找到了,看下面這段代碼:
uiDialog = (self.uiDialog = $('<div></div>'))
.appendTo(document.body)
.hide()
.addClass(uiDialogClasses + options.dialogClass)
.css({
zIndex: options.zIndex
})
// setting tabIndex makes the div focusable
// setting outline to 0 prevents a border on focus in Mozilla
.attr('tabIndex', -1).css('outline', 0).keydown(function(event) {
if (options.closeOnEscape && event.keyCode &&
event.keyCode === $.ui.keyCode.ESCAPE) {
self.close(event);
event.preventDefault();
}
})
.attr({
role: 'dialog',
'aria-labelledby': titleId
})
.mousedown(function(event) {
self.moveToTop(false, event);
}),
它既然也動態(tài)創(chuàng)建一個(gè)div,而且把該div加到了Body上面,然后把dialog中的元素從<div id=test>中移除,加入到該新的div中.....
這就是為什么我們$("#test").empty()后,卻對內(nèi)部的dialog沒有起作用了!而且這有一個(gè)最不好的一個(gè)地方,也是最容易出現(xiàn)內(nèi)存泄露的地方:它動態(tài)的在Body中創(chuàng)建了一個(gè)div,這樣如果窗體不關(guān)閉的話,而你又在不察覺的情況下不斷的使用上面的TestAppend方法來動態(tài)加載DOM,就會創(chuàng)建N個(gè)這樣的div!
其實(shí)這個(gè)問題郁悶的地方不是在如何解決,而且隱藏的很深,很難發(fā)現(xiàn)!那么發(fā)現(xiàn)之后解決起來就變的簡單多了:
if ($('#dialog')[0]) {
$('#dialog').parent().empty();
$('#dialog').parent().remove();
}
當(dāng)前加上這段后代碼后,再做$("#dialog")來測試下,期望的結(jié)果終于出現(xiàn)了!dialog元素消失了!
代碼
復(fù)制代碼 代碼如下:
$('#dialog').dialog({
autoOpen: false,
width: 600,
buttons: {
"Ok": function() {
$(this).dialog("close");
},
"Cancel": function() {
$(this).dialog("close");
}
}
});
在一些JS交互性不多的一般頁面來說,沒有任何問題!但是對于交互性強(qiáng)的,需要動態(tài)加載與釋放DOM的頁面來說,它就是一個(gè)悲劇的東西!為什么這樣說?大家看下下面的例子:
一段簡單的代碼,一個(gè)DIV是通過動態(tài)加載到頁面上,然后對該DIV用Dialog進(jìn)行綁定,以達(dá)到彈出的目的!下面的test元素就是<div id="test"></div>。
代碼
復(fù)制代碼 代碼如下:
function TestAppend() {
$("#test").append('<div id="dialog"><div id="fileQueue"></div> <input type="file" name="uploadify" id="uploadify" />' +
'<a href="javascript:upload();">上傳</a>' +
'<a href="javascript:$(#uploadify).uploadifyClearQueue()">取消上傳</a><div>');
$('#dialog').dialog({
autoOpen: false,
width: 600,
buttons: {
"Ok": function() {
$(this).dialog("close");
},
"Cancel": function() {
$(this).dialog("close");
}
}
});
return false;
}
接著,我需要刪除該DOM元素,一般來說,正常的做法都是$("#test").empty();這行簡單的代碼就完成了!這樣有效嗎?!當(dāng)執(zhí)行完這樣代碼后,你再用$('#dialog')來獲取dialog元素,郁悶的事情發(fā)生了,既然獲取到了!為什么!不是已經(jīng)empty了嗎!
下面我們來看下這一悲劇是如何造成的,
我們把注意點(diǎn)放到$('#dialog').dialog上面,然后看看JQuery的實(shí)現(xiàn)代碼是如何寫的,當(dāng)我們跟蹤代碼到dialog類中的_create方法的時(shí)候,問題的原因找到了,看下面這段代碼:
復(fù)制代碼 代碼如下:
uiDialog = (self.uiDialog = $('<div></div>'))
.appendTo(document.body)
.hide()
.addClass(uiDialogClasses + options.dialogClass)
.css({
zIndex: options.zIndex
})
// setting tabIndex makes the div focusable
// setting outline to 0 prevents a border on focus in Mozilla
.attr('tabIndex', -1).css('outline', 0).keydown(function(event) {
if (options.closeOnEscape && event.keyCode &&
event.keyCode === $.ui.keyCode.ESCAPE) {
self.close(event);
event.preventDefault();
}
})
.attr({
role: 'dialog',
'aria-labelledby': titleId
})
.mousedown(function(event) {
self.moveToTop(false, event);
}),
它既然也動態(tài)創(chuàng)建一個(gè)div,而且把該div加到了Body上面,然后把dialog中的元素從<div id=test>中移除,加入到該新的div中.....
這就是為什么我們$("#test").empty()后,卻對內(nèi)部的dialog沒有起作用了!而且這有一個(gè)最不好的一個(gè)地方,也是最容易出現(xiàn)內(nèi)存泄露的地方:它動態(tài)的在Body中創(chuàng)建了一個(gè)div,這樣如果窗體不關(guān)閉的話,而你又在不察覺的情況下不斷的使用上面的TestAppend方法來動態(tài)加載DOM,就會創(chuàng)建N個(gè)這樣的div!
其實(shí)這個(gè)問題郁悶的地方不是在如何解決,而且隱藏的很深,很難發(fā)現(xiàn)!那么發(fā)現(xiàn)之后解決起來就變的簡單多了:
復(fù)制代碼 代碼如下:
if ($('#dialog')[0]) {
$('#dialog').parent().empty();
$('#dialog').parent().remove();
}
當(dāng)前加上這段后代碼后,再做$("#dialog")來測試下,期望的結(jié)果終于出現(xiàn)了!dialog元素消失了!
您可能感興趣的文章:
- IE下使用jQuery重置iframe地址時(shí)內(nèi)存泄露問題解決辦法
- jquery不會自動回收xmlHttpRequest對象 導(dǎo)致了內(nèi)存溢出
- 使用jQuery Ajax功能時(shí)需要注意的一個(gè)問題(內(nèi)存溢出)
- JQuery1.4+ Ajax IE8 內(nèi)存泄漏問題
- js內(nèi)存泄露的幾種情況詳細(xì)探討
- Javascript 閉包引起的IE內(nèi)存泄露分析
- 容易造成JavaScript內(nèi)存泄露幾個(gè)方面
- 權(quán)威JavaScript 中的內(nèi)存泄露模式
- 關(guān)于js內(nèi)存泄露的一個(gè)好例子
- jQuery內(nèi)存泄露解決辦法
相關(guān)文章
實(shí)例詳解jQuery表單驗(yàn)證插件validate
validate插件是一個(gè)基于jquery的表單驗(yàn)證插件了里面有許多的常用的一些驗(yàn)證方法我們可以直接調(diào)用,具體的我們一起來看看2016-01-01jQuery使用模式窗口實(shí)現(xiàn)在主頁面和子頁面中互相傳值的方法
這篇文章主要介紹了jQuery使用模式窗口實(shí)現(xiàn)在主頁面和子頁面中互相傳值的方法,涉及jQuery模式窗口及參數(shù)傳遞相關(guān)技巧,需要的朋友可以參考下2016-03-03Jquery Validate 正則表達(dá)式實(shí)用驗(yàn)證代碼大全
jQuery.validate 的正則驗(yàn)證功能,包括手機(jī)號碼、電話號碼、郵政編碼、QQ號碼、IP地址、字母和數(shù)字、中文的驗(yàn)證等2013-08-08jQuery AJAX 方法success()后臺傳來的4種數(shù)據(jù)詳解
今天小編就為大家分享一篇jQuery AJAX 方法success()后臺傳來的4種數(shù)據(jù)詳解,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-08-08