快捷搜索:  xxx  as  1111

DTree中致命的递归

本文示例源代码或素材下载

前不久我颁发过一篇文章,名字叫《可爱又可恨的梅花雪 》,此中先容了meizz大年夜侠台甫鼎鼎的梅花雪树控件,而且对此中碰到的一些小问题进行了改造,后来有人评论说梅花雪树太繁杂,不如DTree来得简便,这个确凿如斯!DTree的代码看起来要简便很多,所实现的功能也还很富厚(只管还没有梅花雪树那么强大年夜),在一样平常的菜单和导航节制中应用会很方便,而且不会有什么问题。我在改造梅花雪树之前,也曾考试测验过DTree,并且也对此中的一些措施进行了改造,但后来不得不放弃,由于DTree中致命的递归导致了在大年夜数据量构造树的节点时js报客栈溢出的差错!

先看看我对DTree的改造。

1. DTree中图片的引用路径被写逝世在js代码里,这个完全可以写成一个变量,在必要时变动。

var imgPath = "img";

// Tree object

function dTree(objName) {

this.config = { target: null, folderLinks: true, useSelection: true, useCookies: true, useLines: true, useIcons: true, useStatusText: false, closeSameLevel: false, inOrder: false };

this.icon = { root: imgPath + "/base.gif", folder: imgPath + "/folder.gif", folderOpen: imgPath + "/folderopen.gif", node: imgPath + "/page.gif", empty: imgPath + "/empty.gif", line: imgPath + "/line.gif", join: imgPath + "/join.gif", joinBottom: imgPath + "/joinbottom.gif", plus: imgPath + "/plus.gif", plusBottom: imgPath + "/plusbottom.gif", minus: imgPath + "/minus.gif", minusBottom: imgPath + "/minusbottom.gif", nlPlus: imgPath + "/nolines_plus.gif", nlMinus: imgPath + "/tree/nolines_minus.gif" };

this.obj = objName;

this.aNodes = [];

this.aIndent = [];

this.root = new Node(-1);

this.selectedNode = null;

this.selectedFound = false;

this.completed = false;

}

2. DTree中没有用于获取当选择节点的text值的措施,而此中的test措施完全可以被用来改造。

// Get all selected nodes text (e.g. a,b,c,d,e)

dTree.prototype.getText = function () {

var value = new Array();

for (var n = 0; n

3. DTree中没有斟酌节点的CheckBox的disabled状态,因为节点华夏先就包孕CheckBox控件,以是可以直接应用它的disabled属性来进行节制。

var treeMode = "General"; //General or Special

// Event of the node check

dTree.prototype.checkNode = function(nodeId) {

var check = document.getElementById(("c" + this.obj) + nodeId);

var node = this.getNode(nodeId);

node.check = check.checked;

if (check.checked) {

if (treeMode == "Special") {

this.enableChildreNode(node, true);

}

else {

this.checkChildreNode(node, true);

}

//this.checkParentNode(node, true);

} else {

if (treeMode == "Special") {

this.enableChildreNode(node, false);

}

else {

this.checkChildreNode(node, false);

}

}

};

// Check all child nodes of the current node (recursive)

dTree.prototype.checkChildreNode = function (node, check) {

for (var i = 0; i  0) {

this.checkChildreNode(node.cNode[i], check);

}

}

};

dTree.prototype.enableChildreNode = function(node, check) {

for (var i = 0; i  0) {

this.enableChildreNode(node.cNode[i], check);

}

}

}

其次,细查DTree中的代码,发明很多地方着实都是用递归实现的算法,这也便是为什么我只管办理了在递归中add节点的问题后照样会赓续地呈现客栈溢出的差错。来看看这些导致差错的致命的递归。

1. checkChildreNode措施中的递归在check一个父节点的时刻会触发,假如这个父节点下的分支和子节点分外多,纵然不激发客栈溢出的差错,速率预计也很慢。

dTree.prototype.checkChildreNode = function (node, check) {

for (var i = 0; i  0) {

this.checkChildreNode(node.cNode[i], check);

}

}

};

2. 最致命的处所在这里,render树时会调用addNode措施,而addNode措施又会赓续调用node措施,这两个措施之间形成了一个递归调用的历程,假如节点过多,会激发客栈溢出的差错。这个递归同样会由dtree.tostring()措施引起,它调用addNode,然后addNode调用node,之后node又调用addNode...如斯反复,终极形成了罪责的深渊!

// Creates the node icon, url and text

dTree.prototype.node = function (node, nodeId) {

var str = "

" + this.indent(node, nodeId);

if (this.config.useIcons) {

if (!node.icon) {

node.icon = (this.root.id == node.pid) ? this.icon.root : ((node._hc) ? this.icon.folder : this.icon.node);

}

if (!node.iconOpen) {

node.iconOpen = (node._hc) ? this.icon.folderOpen : this.icon.node;

}

if (this.root.id == node.pid) {

node.icon = this.icon.root;

node.iconOpen = this.icon.root;

}

if (node.check && node.check != "") {

//  onclick='alert(nodeId)'

str += "";

} else {

str += "";

}

}

if (node.url) {

str += "";         }     }     str += node.name;     if (node.url || ((!this.config.folderLinks || !node.url) && node._hc)) {         str += "";

}

str += "

";

if (node._hc) {

str += "

";

str += this.addNode(node);

str += "

";

}

this.aIndent.pop();

return str;

};

您可能还会对下面的文章感兴趣: