我们正在使用YUI的onclick事件,但我们会快速创建和删除圆顶节点,这会导致内存泄漏。
考虑下面的示例代码,我们有很多次3个嵌套的div。顶部和底部div附加了YUI onclick事件。什么是摆脱那些dom元素而不是泄漏内存的正确方法:
我真的没有任何想法。如您所见,我尝试实现自己的destroy
函数。实际上destroy
有效且不泄漏,但速度很慢。
destroy2
功能是' copy'我们用来调试问题的YUI销毁功能。看起来YUI的递归清理无法在_instances
字典中找到子节点
<!DOCTYPE html5>
<html>
<head>
<script src="http://yui.yahooapis.com/3.4.1/build/yui/yui-min.js"></script>
</head>
<body>
<div id="main">hi there</div>
<script>
YUI().use("node", "event", function(Y) {
window.Y = Y;
function destroy(node) {
(new Y.Node(node)).destroy();
var children = node.children;
for (var i = 0; i<children.length; i++) {
destroy(children[i]);
}
}
function destroy2(node, recursive) {
var UID = Y.config.doc.uniqueID ? 'uniqueID' : '_yuid';
// alert(1);
if (recursive) {
var all = node.all("*");
// alert(all);
Y.NodeList.each(all, function(n) {
instance = Y.Node._instances[n[UID]];
// alert(instance);
if (instance) {
destroy2(instance);
}
});
}
node._node = null;
node._stateProxy = null;
delete Y.Node._instances[node._yuid];
// node.destroy();
}
var main = new Y.Node("#main");
var divs = [];
var iter = 0;
Y.later(10, window, function() {
iter ++ ;
var i;
for (i=0; i<divs.length; i++) {
var d = divs[i];
d.parentNode.removeChild(d);
// (new Y.Node(d)).destroy(true);
//destroy(d);
//destroy2(new Y.Node(d), true);
(new Y.Node(d)).destroy(true);
}
divs = [];
for (i=0; i<1000; i++) {
var d = document.createElement("div");
var i1;
var i2;
d.appendChild(i1=document.createElement("div"));
i1.appendChild(document.createTextNode('inner 1'));
i1.appendChild(i2=document.createElement("div"));
i2.appendChild(document.createTextNode('inner 2'));
Y.on("click", function() {
alert("inner click")
}, i2);
// try to tell YUI to make Node elements
Y.Node.one(d);
Y.Node.one(i1);
Y.Node.one(i2);
// new Y.Node(d);
// new Y.Node(i1);
// new Y.Node(i2);
d.appendChild(document.createTextNode("this is div " + iter + " " + i));
Y.on("click", function(){ alert("you clicked me");}, d);
main.appendChild(d);
//divs.push(i2);
divs.push(d);
}
}, null, true);
})
</script>
</body>
</html>
答案 0 :(得分:6)
我不确定你在这里想要完成什么,但是在所包含的代码中有一些突出的东西:
var Y = YUI().use(…)
- use()
返回YUI实例。无需指定window.Y = Y;
Y.one(el)
代替new Y.Node(el)
或Y.Node.one(el)
Y.Node.create('<div><div>inner 1<div>inner2</div></div></div>')
。您可能不需要每个div的Node实例这些要点中最重要的是#3和#4。如果您使用Node.create
(或append
,insert
,prepend
等),则传入的标记将不会为每个元素创建节点,只会创建最外层元素。如果您使用事件委派,则不需要单独的节点,这意味着您可以添加div结构并立即调用node.destroy()
(注意不要传递true
,因为内部标记没有需要清除的节点)。 node.destroy()
将清除事件侦听器,这是因为您正在使用事件委派而没有,并且在_instances
字典中删除节点以在任何用户交互之前释放内存。如果用户单击其中一个节点,则委托处理程序将捕获该事件,并为e.target
元素创建节点。您可以在事件处理程序中调用this.destroy()
来重新清除target
的节点。
YMMV,考虑到您的代码段并未反映真实的用例。您也可以在freenode上停留#yui以获得帮助或解决问题。
答案 1 :(得分:0)
以下是我为避免内存泄漏而采取的措施:
var destroy = function(dom) {
var ynode = new Y.Node(dom);
ynode.purge(true);
ynode.destroy(true);
}
我不得不说我对YUI文档说这个YUI销毁函数非常失望。
使用true作为第一个参数,它的作用类似于node.purge(true)。该 destroy方法不仅仅是分离事件订阅者。阅读 API文档了解详细信息。 http://yuilibrary.com/yui/docs/event/
我在YUI中考虑这个错误,因为当你以递归方式调用destroy时,它不会调用递归清除。另外看起来上面的破坏功能在Firefox 8上很慢(也许是其他版本)我在dom树上编写了我自己的递归并调用了purge
和destroy
没有true
。