|
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
|---|---|
| 作者 | 正文 |
|
时间:2008-03-18
EXT的destroy方法是不是存在漏洞?销毁的不彻底?
利用 http://fins.javaeye.com/blog/172891 提到的工具,在IE下对EXT进行测试 只是一个简单的页面,页面内只是简单的定义一个简单的window ,如下
var win=new Ext.Window({title:"my window",
width:400,
draggable : false,
shadow : false,
resizable : false,
shim :false,
autoDestroy : true,
height:300});
关闭这个window时 产生很多ie无法自动回收的孤立结点 每次创建 关闭 创建 关闭 .... 孤立结点都会越来越多 也许这是IE的错 但是EXT不应该忽视IE的 毕竟IE的占有率在那里放着呢 还请大家帮忙分析分析 我看了一下 window/panel的destroy方法似乎确实存在着一些缺陷啊 我重写了 window的destroy方法,效果提升一些,一些顽固结点可以删除了 但是还剩下一下更加顽固的结点无法删除
Ext.Window.prototype.beforeDestroy = function(){
Ext.Window.superclass.beforeDestroy.call(this);
Ext.destroy(
this.header,
this.tbar,
this.bbar,
this.footer,
this.body,
this.bwrap,
this.focusEl,
this.toolTarget,
this.resizer,
this.dd,
this.proxy,
this.mask
);
this.header=null;
this.tbar=null;
this.bbar=null;
this.footer=null;
this.body=null;
this.bwrap=null;
this.focusEl=null;
this.toolTarget=null;
this.resizer=null;
this.dd=null;
this.proxy=null;
this.mask=null;
}
这个问题如果不弄明白, 在一个复杂的ext页面内,随着操作的增加 内存消耗也将越来越大. deskto那个例子里的 窗口 大家打开关闭打开关闭 几个来回之后内存占用就会达到6 7十M了. 我怀疑 ext的各个组件的destroy方法内部的实现考虑的不够全面, 销毁内容 和销毁顺序 不当造成部分元素无法销毁. 希望大家能够一起讨论分析一下ext的问题到底处在哪里 声明:JavaEye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
| 返回顶楼 | |
|
时间:2008-03-18
jack要让我疯狂了!!!!
为了找出问题所在 我一行行的分析 2.02版本代码的 太辛苦了 看到一个地方彻底崩溃了 Template.js 204行 return returnEl ? Ext.get(newNode, true) : newNode; 注意 Ext.get(newNode, true) 再来看 Ext.get 方法的代码 Element.js 2880行
El.get = function(el){
var ex, elm, id;
if(!el){ return null; }
if(typeof el == "string"){ // element id
if(!(elm = document.getElementById(el))){
return null;
}
if(ex = El.cache[el]){
ex.dom = elm;
}else{
ex = El.cache[el] = new El(elm);
}
return ex;
}else if(el.tagName){ // dom element
if(!(id = el.id)){
id = Ext.id(el);
}
if(ex = El.cache[id]){
ex.dom = el;
}else{
ex = El.cache[id] = new El(el);
}
return ex;
}else if(el instanceof El){
if(el != docEl){
el.dom = document.getElementById(el.id) || el.dom; // refresh dom element in case no longer valid,
// catch case where it hasn't been appended
El.cache[el.id] = el; // in case it was created directly with Element(), let's cache it
}
return el;
}else if(el.isComposite){
return el;
}else if(Ext.isArray(el)){
return El.select(el);
}else if(el == document){
// create a bogus element object representing the document object
if(!docEl){
var f = function(){};
f.prototype = El.prototype;
docEl = new f();
docEl.dom = document;
}
return docEl;
}
return null;
};
// 省去一些.....
Ext.get = El.get;
我是绞尽脑汁也没弄明白那个true是做什么的 我怀疑这个地方jack弄错了 他本意可能是要给 get弄一个是否从cache里取对象的参数吧 但是没有写. |
|
| 返回顶楼 |
请登录后投票
|
|
时间:2008-03-18
ext1.1 里启用垃圾回收后,等30秒才从Element的cache里清除。
刷新页面后内存还占用? |
|
| 返回顶楼 |
请登录后投票
|
|
时间:2008-03-18
问题的根本原因找到了 :)
一会儿单独发帖讨论 |
|
| 返回顶楼 |
请登录后投票
|
|
时间:2008-03-18
下面这段代码也有问题
看来 ext的 Ext.destroy 果然不够强大 问题还是出在事件管理方面 疑惑中
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" type="text/css" href="../resources/css/ext-all.css" />
<script type="text/javascript" src="../adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="../ext-all.js"></script>
<script type="text/javascript">
function alertMsg(){
alert('click div c');
}
function addEventDiv(){
if (!Ext.get("div1") ){
return;
}
// 使用下面这种方式注册事件 , 那么ext无法正确的移除
Ext.get("div1").on("click",alertMsg);
}
Ext.onReady(function(){
Ext.get("btn1").on("click",addEventDiv);
Ext.get("btn2").on("click",function(){ Ext.destroy(Ext.get("div1")); });
});
</script>
</head>
<body >
<input id="btn1" type="button" value=" 为 div1 添加事件 " />
<input id="btn2" type="button" value=" 移除 div1 " />
<div id="div1">I'm div 1</div>
</body>
</html>
|
|
| 返回顶楼 |
请登录后投票
|
|
时间:2008-03-18
前几天也研究过这里的代码,看不出漏洞在那,lisenter的移除,节点的移除都是正确的。。。
|
|
| 返回顶楼 |
请登录后投票
|
|
时间:2008-03-18
en 代码上确实没找到什么问题
但是实际情况就是无法移除 而如果用下面的方法给上面代码中的 div注册事件 那么就可以移除:
Ext.get("div1").on("click",function(){ alertMsg() });
|
|
| 返回顶楼 |
请登录后投票
|
|
时间:2008-03-18
但其实ext已经用传入的function包装了一个新的function,然后才绑定到节点去。
|
|
| 返回顶楼 |
请登录后投票
|
|
时间:2008-03-18
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" type="text/css" href="/script/yuiExt/resources/css/ext-all.css" />
<script type="text/javascript" src="/script/yuiExt/adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="/script/yuiExt/ext-all.js"></script>
<script type="text/javascript">
function alertMsg(){
alert('click div c');
}
function addEventDiv(){
if (!Ext.get("div1") ){
return;
}
// 使用下面这种方式注册事件 , 那么ext无法正确的移除
Ext.get("div1").on("click",alertMsg);
}
Ext.onReady(function(){
Ext.get("btn1").on("click",addEventDiv);
Ext.get("btn2").on("click",function(){
Ext.destroy(Ext.get("div1"));
alert(alertMsg._handlers.length);
alert(alertMsg._handlers[0][0]);
alert(alertMsg._handlers[0][1]);
alert(alertMsg._handlers[0][2]);
});
});
</script>
</head>
<body >
<input id="btn1" type="button" value=" 为 div1 添加事件 " />
<input id="btn2" type="button" value=" 移除 div1 " />
<div id="div1">I'm div 1</div>
</body>
</html>
发现问题在于ext的 wrap function,就是listener是global的话就会有问题。 见 EventManager.js的140行:
fn._handlers = fn._handlers || [];
fn._handlers.push([Ext.id(el), ename, h]);
这里给传入的listener加了_handlers属性,stopLisener负责清除,那么就能正确的处理。 但是destroy直接调用了E.purgeElement...,这个方法好像没办法看到原来的listen,所以,没办法正确的清除_handlers,而_handlers引用了element |
|
| 返回顶楼 |
请登录后投票
|
|
时间:2008-03-18
nihongye 的分析是正确的。
on的加入是通过EventManager的addListener方法来做的,这里在每个fn上绑定了_handlers,purgeElement的时候通过Ext.lib.Event的removeListener方法, 见300行
delete listeners[index][this.WFN];
delete listeners[index][this.FN];
但是这里是只是删除了fn,没有清楚掉里面的handlers,而handlers有el的引用,因为没法清楚对象.而这个时候fn也就是alertMsg是在window下的,我测了一下,单纯删除他是没用的,必须wrap一下,所以出现了你说的必须用function(){ alertMsg() } 才正确的情况 |
|
| 返回顶楼 |
请登录后投票
|







