背景:受this question和this question启发,关于D3内存的使用情况,我决定深入研究它的工作原理,很快就会发现cautions about repeated add/remove of DOM nodes in IE。 < / p>
为了隔离D3正在做的其他事情,我首先尝试了每秒添加/删除1000个圆圈的基本SVG案例:
var count = 1000;
var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
svg.setAttribute('width', '800');
svg.setAttribute('height', '800');
document.body.appendChild(svg);
function update() {
// remove existing circles
var circles = svg.querySelectorAll("circle")
for (var i = circles.length - 1; i >= 0; i--) {
var parent = circles[i].parentNode;
if (parent) parent.removeChild(circles[i]);
};
// add new ones. Yes, would make more sense to update the x,y on the existing
// circles but this is to show what happens in IE with lots of nodes being added/removed
for (var j = count - 1; j >= 0; j--) {
var node = document.createElementNS("http://www.w3.org/2000/svg", 'circle');
node.id = 'id' + Math.random();
node.setAttributeNS(null, "cx", Math.random()*800);
node.setAttributeNS(null, "cy", Math.random()*800);
node.setAttributeNS(null, "r", 5);
node.setAttributeNS(null, "fill", "blue");
svg.appendChild(node);
};
}
setInterval(update, 1000);
我发现这在IE9和IE10中都会慢慢泄漏内存。请参阅此处查看实时版本:http://bl.ocks.org/explunit/6413259
我可以做些什么(如果有的话)来防止泄漏,以及这对于如何编写针对IE的D3代码添加/删除大量节点有什么影响?
其他说明:
受this article的启发,我尝试了一种简单的节点池方法,将已删除的节点推送到堆栈:
if (parent) circlePool.push( parent.removeChild(circles[i]) );
稍后重复使用它们:
var node;
if (circlePool.length == 0) {
node = document.createElementNS("http://www.w3.org/2000/svg", 'circle');
} else {
node = circlePool.pop();
//TODO: clear out attributes of the node
}
但这没有任何区别。
答案 0 :(得分:2)
到目前为止我唯一能够帮助IE内存使用的是不为节点分配ID,或者为它们分配在动画迭代中重复的ID:
node.id = 'id' + j;
请在此处查看实时版:http://bl.ocks.org/explunit/6413371
我认为在删除DOM节点之前将ID置零会做同样的事情,但这没有效果。
我真的不喜欢这个答案所以我希望其他人能够更好地解释为什么节点池方法不起作用。
但是现在,开发人员使用D3的故事的道德:如果你反复添加然后删除大量具有唯一ID的节点(例如来自.ajax调用从db中获取记录),你可能在内存泄漏的危险。