惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Hacker News - Newest:
Hacker News - Newest: "LLM"
C
Cisco Blogs
L
LINUX DO - 热门话题
S
Schneier on Security
NISL@THU
NISL@THU
T
Threatpost
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Latest news
Latest news
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
量子位
Stack Overflow Blog
Stack Overflow Blog
The GitHub Blog
The GitHub Blog
月光博客
月光博客
Cyberwarzone
Cyberwarzone
B
Blog
G
GRAHAM CLULEY
L
Lohrmann on Cybersecurity
Microsoft Security Blog
Microsoft Security Blog
Vercel News
Vercel News
小众软件
小众软件
M
MIT News - Artificial intelligence
I
InfoQ
aimingoo的专栏
aimingoo的专栏
C
CXSECURITY Database RSS Feed - CXSecurity.com
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
美团技术团队
Google DeepMind News
Google DeepMind News
T
The Blog of Author Tim Ferriss
Help Net Security
Help Net Security
WordPress大学
WordPress大学
V
Vulnerabilities – Threatpost
T
Tenable Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
N
Netflix TechBlog - Medium
MyScale Blog
MyScale Blog
Blog — PlanetScale
Blog — PlanetScale
Y
Y Combinator Blog
Google DeepMind News
Google DeepMind News
D
Docker
MongoDB | Blog
MongoDB | Blog
Forbes - Security
Forbes - Security
H
Hacker News: Front Page
A
About on SuperTechFans
L
LINUX DO - 最新话题
B
Blog RSS Feed
D
DataBreaches.Net
博客园 - 司徒正美
Recorded Future
Recorded Future
G
Google Developers Blog
Hugging Face - Blog
Hugging Face - Blog

博客园 - Kevin-moon

在IE中本地浏览与服务器浏览同一Html后,出现了奇异的结果 JQuery另类视角-动态执行脚本的BUG JQuery另类视角-动态扩展对象 - Kevin-moon - 博客园 如何重构代码-简单、灵活的实现对象复制 如何重构代码-重构计划 如何重构代码-思路和方法 谈谈多线程的思维方式 简单的数据移动算法(C#) [ASP.NET MVC]-理解Routing 笑死人的十项大奖 深入APM,实现自己的APM [Windbg基础]-了解Symbols 深入线程,实现自定义的SynchronizationContext 重温ASP.NET的配置信息(简单、常用) 奇妙的SynchronizationContext 线程之间的通讯---SynchronizationContext "对象"到"山寨对象"的完整转换 我真的就只能在远方看你吗?!!! "测试驱动开发(TDD)" 动态进行"自定义公式"计算
如何避免JQuery Dialog的内存泄露
Kevin-moon · 2010-06-18 · via 博客园 - Kevin-moon

  对于页面来说,JQuery中的Dialog从效果上来说还可以,而且使用简单,只要短短几行绑定的代码就可以实现弹出效果。

代码

$('#dialog').dialog({
                 autoOpen: 
false,
                 width: 
600,
                 buttons: {
                     
"Ok": function() {
                         $(
this).dialog("close");
                     },
                     
"Cancel": function() {
                         $(
this).dialog("close");
                     }
                 }
             });

在一些JS交互性不多的一般页面来说,没有任何问题!但是对于交互性强的,需要动态加载与释放DOM的页面来说,它就是一个悲剧的东西!为什么这样说?大家看下下面的例子:

  一段简单的代码,一个DIV是通过动态加载到页面上,然后对该DIV用Dialog进行绑定,以达到弹出的目的!下面的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();这行简单的代码就完成了!这样有效吗?!当执行完这样代码后,你再用$('#dialog')来获取dialog元素,郁闷的事情发生了,既然获取到了!为什么!不是已经empty了吗!

  下面我们来看下这一悲剧是如何造成的,

  我们把注意点放到$('#dialog').dialog上面,然后看看JQuery的实现代码是如何写的,当我们跟踪代码到dialog类中的_create方法的时候,问题的原因找到了,看下面这段代码:

_create

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(
falseevent);
                }),

  它既然也动态创建一个div,而且把该div加到了Body上面,然后把dialog中的元素从<div id=test>中移除,加入到该新的div中.....

  这就是为什么我们$("#test").empty()后,却对内部的dialog没有起作用了!而且这有一个最不好的一个地方,也是最容易出现内存泄露的地方:它动态的在Body中创建了一个div,这样如果窗体不关闭的话,而你又在不察觉的情况下不断的使用上面的TestAppend方法来动态加载DOM,就会创建N个这样的div!

  其实这个问题郁闷的地方不是在如何解决,而且隐藏的很深,很难发现!那么发现之后解决起来就变的简单多了:

if ($('#dialog')[0]) {
    $(
'#dialog').parent().empty();
    $(
'#dialog').parent().remove();
}

 当前加上这段后代码后,再做$("#dialog")来测试下,期望的结果终于出现了!dialog元素消失了!