Javascript 如何使用YUI进行适当的内存管理以避免泄漏
我们正在使用YUI的onclick事件,但我们会快速创建和删除dome节点,这会导致内存泄漏 考虑下面的示例代码,我们多次使用3个嵌套div。顶部和底部div附带了YUI onclick事件。去除这些dom元素而不泄漏内存的正确方法是什么: 我真的没有主意了。如您所见,我尝试实现了我们自己的Javascript 如何使用YUI进行适当的内存管理以避免泄漏,javascript,dom,memory-leaks,yui,Javascript,Dom,Memory Leaks,Yui,我们正在使用YUI的onclick事件,但我们会快速创建和删除dome节点,这会导致内存泄漏 考虑下面的示例代码,我们多次使用3个嵌套div。顶部和底部div附带了YUI onclick事件。去除这些dom元素而不泄漏内存的正确方法是什么: 我真的没有主意了。如您所见,我尝试实现了我们自己的destroy函数。实际上,destroy工作正常,不会泄漏,但速度很慢 destroy 2函数是YUI destroy函数的“复制”,我们使用它来调试问题所在。看起来YUI的递归清理在\u实例字典中找不到子
destroy
函数。实际上,destroy
工作正常,不会泄漏,但速度很慢
destroy 2
函数是YUI destroy函数的“复制”,我们使用它来调试问题所在。看起来YUI的递归清理在\u实例
字典中找不到子节点
<!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>
你好
YUI()。使用(“节点”、“事件”、函数(Y){
窗口Y=Y;
功能销毁(节点){
(新的Y.Node(Node)).destroy();
var children=node.children;
对于(var i=0;i我不确定您在这里试图实现什么,但在所包含的代码中有几点很突出:
var Y=YUI()。use(…)
--use()
返回YUI实例。无需分配window.Y=Y;
使用Y.one(el)
代替newy.Node(el)
或Y.Node.one(el)
在每个内部div上使用而不是订阅click事件
使用Y.Node.create('internal1inner2')
。每个div可能不需要节点实例
通过混合原始DOM交互和YUI节点,您可能会在长期内为自己创建更多的工作
这些要点中最重要的是#3和#4。如果使用节点,则创建
(或附加
,插入
,前置
,等等),传入的标记不会为每个元素创建节点,只有最外层的元素。如果使用事件委派,则不需要单独的节点,这意味着您可以添加div结构并立即调用node.destroy()
(注意不要传递true
,因为内部标记没有需要清除的节点).node.destroy()
将清除事件监听器,因为您使用的是事件委派,所以您没有该监听器,并在任何用户交互之前从\u instances
字典中删除该节点以释放内存。如果用户单击其中一个节点,该事件将被委派处理程序捕获,并将为e.target创建一个节点e> 元素。您可以在事件处理程序中自由调用this.destroy()
,以重新清除目标的节点
YMMV,考虑到您的代码片段没有反映真实的用例。您也可以在freenode上访问#yui以获得帮助或了解问题。以下是我为避免内存泄漏而采取的措施:
var destroy = function(dom) {
var ynode = new Y.Node(dom);
ynode.purge(true);
ynode.destroy(true);
}
我必须说,我对YUI文档非常失望,它说YUI销毁函数是这样的
第一个参数为true时,它的工作方式与node.purge(true)类似
destroy方法的作用不仅仅是分离事件订阅服务器
API文档以获取详细信息。
我在YUI中考虑了这个bug,因为当调用递归破坏时它不调用递归清除。而且看起来上面的销毁函数在Firefox 8上很慢(也许其他版本也一样)我确实在DOM树上写下了自己的递归并称为<代码>清除< /代码>。
和<代码>销毁< /代码>没有<代码>真< /代码> .使用事件委派可能是一种选择,但我只是尝试修复一些遗留代码。出于同样的原因,我们已经混合了<代码> yi节点和原始<代码> DOM<代码>。我们将考虑使用委托,尽管它更容易为我们在特定节点上附加事件。感谢您的回答如果您认为行为是一个bug,您应该将其提交到,根据记录,这个用例在YUI 3的最新版本中不可复制,因此显然这已经解决了。