- 浏览: 5687 次
- 性别:
- 来自: 上海
最新评论
-
fregen:
楼主应该去看看jquery ui
遵循MVC模式,效仿JTree思想,用javascript实现树形结构教程 -
lijiabin102:
我说两句啊……
(1)这样构建的树从数据库里拉几千条数据显示的 ...
遵循MVC模式,效仿JTree思想,用javascript实现树形结构教程 -
gwallan:
不错不错,思路很清晰
遵循MVC模式,效仿JTree思想,用javascript实现树形结构教程 -
srt:
这是楼主的代码 我给test了一下
遵循MVC模式,效仿JTree思想,用javascript实现树形结构教程 -
hanjs:
lz的文章很有启发性。如果在把tree render加上就更丰 ...
遵循MVC模式,效仿JTree思想,用javascript实现树形结构教程
1.引言
正如大家所看到的,这又是一位编程者再发明轮子了,我猜想我在写这篇文章的时候也许还有千千万万个重复发明轮子的程序员正在埋头思考着类似于“如何实现关于树形结构的展示”的问题。
关于众多的实现树状结构的解决方案多不胜数,但我觉得这并不能阻挡我们实现自己的树的脚步。我写下来以便自己能回顾整理开发思路并分享我的经验。
2.一个失败的作品--实现一个一层树的解决方案
这是一个最普遍的解决方案,思想是:直接在网页中写你所需要的div作为树的节点,然后写一个javascript程序来控制树的位置和显示。
上面的代码中,一个div(节点)包括了 id号(供js来引用),图片(根目录,文件夹或文件),带有连接的文字说明,还有改div的位置信息。
这个解决方案的关键在于:使用div的嵌套实现树状结构的父子关系,这样我们就可以的到某个特定节点的id号,然后利用js的方法得到内嵌于该div中的子div(节点),对他进行隐藏/显示的操作。
我们还需要完成上面那个更换图片把手的方法
这样我们已经基本完成了对一个一层树状结构的构造了。
一条好消息和一条坏消息。好消息是:我们得到我们想要的轮子了。坏消息是:轮子是方的。
上面的方案经不起推敲
1)我们无法扩展这棵树。1个1层结构的树起不了什么作用,我们需要一个能满足目录层次更深的树。虽然我们可以再增加div的深度。但js可能无法实现复杂的循环。
2)我们不能碰他,因为这个代码非常脆弱。我们唯一可以碰的也许就是那几个带连接的名字
3.从失败走向成功
3.1从JTree得到的启发
在我们的失败的例子中已经展示了足够多的操作树的方法,而失败的主要原因是我们使用了一个方形的磨具来制造我们的轮子。因此我们需要有一个良好的磨具--MVC。我们可以看看JAVA中的JTree是如何实现树状结构的。
JTree主要用于在SWING中展示树,而模型的制作是交给DefaultTreeModel来完成的我们可以这样得到一棵JAVA的树。
JAVA已经给我们造好了房子,我们要做的是需要搬进去住就行了。而我们现在一无所有,需要从拌水泥开始。但是我们已经拥有了一张不错的设计图纸(MVC)和熟练的制造技术(javascript方法),那还有什么可担心的呢。
3.2付诸实施
在真正动手之前,必须清醒地认识到,我们不能让dom做我们的模型。我们必须把模型从dom中分离开来,让dom作为VIEW。(失败的例子中dom担负了太多的角色)。好了我们可以开始了。
3.2.1实现node
任何树都有节点。因此我们需要一个node类。
类的属性包括:id号(用来唯一确定node),nodeName(节点名字),parentNode(父节点),childNodes(子结点数组)
status(如果节点是文件夹,用来确定是打开还是关闭),visible(是可见还是被隐藏了)
我们的node类看上去像这样:
3.2.2实现treeModel
毫无疑问,一棵树的模型也是有很多树的节点组成的。我们在这个类中组装我们的node节点。
3.2.3实现treeView
我们已经构建好了模型,接下来就是展示他。这是一个比较艰难的部分,但主要思想很简单:将node类型转换成相应的div,然后添加到body上就能呈现了。
3.2.3查看结果
我们已经完成了一棵树的构造,虽然是静态的,我们可以在body中调用tree()方法得到树
你可以在构造函数中去掉一个三级节点的时候,二级节点将会自动从一个文件夹变成文件的图标!
4.继续完善
4.1实现事件
接下来我们需要让这棵树动起来,我们需要为表示把手的img提供一个onclick事件。失败的模型中,我们直接改变div的style.display或visibility属性。而这个方案中我们只是让div作树的呈现,所以我们改变策略,让事件通知我们的tremodel模型。
4.1.1实现事件的关键:ID
要让treeview和treeModel联系起来的方法是:给他们分配同一个id。前面的代码中我们并没有初始化id。我们现在需要编写一个方法,实现node.id的自动编号。
在treeMode()函数中调用addId(root);
在tree()函数内的getDiv()函数中为代表把手的图片添加和node.id相同的id号
测试一下这段代码,正确的弹出了id号
4.1.2根据id号找node
我们已经将div中的把手图片的id号和模型中node的id号对上了,只要根据这个id号就能找到node节点对象,然后就能轻易地改变node和他子结点的属性。我们需要在treeMode中添加一个findNodeById(node,id)方法
4.1.3实现展开/收缩方法
如果一个节点是的状态是关闭的,那么它所有的子孙节点都不可见。
但是一个节点如果是展开的,并不代表它所有的子孙节点都可见!试想一下如果1个2级文件夹试关闭的,那么打开一个1级文件夹后,2级文件夹内的文件还是不可见,因此,打开动作执行后文件的可见性只和文件夹的status(closed or opened)有关
可以看到这个方法应该作为节点的方法,所以我们在node类型中添加展开方法,而不是在树中。树的任务只需要调用一下node的setChildNodeClosed()。
为我们的treeMode增加一个setStatus()方法,方法内部是查找id号,然后改变一系列node的status
最后在我们的onclick事件中添加这个changeStatus()方法
4.1.4检验代码
运行一下代码,点击chapter1的收缩图标后,浏览器中又增加了一棵树!我知道这并不是你想要的,但我们可以观察一下新加入的树,它的确正确的关闭了文件夹!我们最后需要作的仅仅是去掉老的那个树
4.1.5刷新树
要去掉已经在网页中显示的树,就要找到对应的div,从document.body中removeChild便可。但遍历整个页面并不可行,第一页面很大的话效率降低,第二容易造成误删。解决方法是我们可以给课div树做一个快照或索引,按照索操作不就行了吗。大白话就是--做一个存放div的数组。
5.测试并总结
测试你的代码,不出意外你将会的到一个比较完美的树形结构,有多完美?我们可以稍微考验一下我们的程序
以上基本是按我如何一步步地实现这棵有点复杂的树的开发思路,JAVA 中JTree和DefaultTreeModel给与我很大的启发,使我完成了从最早的方形轮子到圆形轮子的进化过程,过程中不时遭遇到javascript语言制造的小麻烦和模型完善的困难。但完成之后也对MVC这种编程思想有了更进一步的认识。看完此文希望诸位对改变“重复发明”的偏见。
正如大家所看到的,这又是一位编程者再发明轮子了,我猜想我在写这篇文章的时候也许还有千千万万个重复发明轮子的程序员正在埋头思考着类似于“如何实现关于树形结构的展示”的问题。
关于众多的实现树状结构的解决方案多不胜数,但我觉得这并不能阻挡我们实现自己的树的脚步。我写下来以便自己能回顾整理开发思路并分享我的经验。
2.一个失败的作品--实现一个一层树的解决方案
这是一个最普遍的解决方案,思想是:直接在网页中写你所需要的div作为树的节点,然后写一个javascript程序来控制树的位置和显示。
<!-- 树状结构的节点,正如看到的那样,这样的节点是直接写在网页上的--> <body> <div id="root" style="position:relative"><img src="root.gif"/><a href="#">射雕英雄传</a><br> <div id="0" style="position:relative;left:0px"><img src="childnoslibminus.gif" onclick="hide(0,this)"/><img src="folderopen.gif"/><a href="#">目录</a> <div style="position:relative;left:20px"><img src="t.gif"/><img src="page.gif"/><a href="#">目录1</a></div> <div style="position:relative;left:20px"><img src="turnline.gif"/><img src="page.gif"/><a href="#">目录2</a></div> </div> </body>
上面的代码中,一个div(节点)包括了 id号(供js来引用),图片(根目录,文件夹或文件),带有连接的文字说明,还有改div的位置信息。
这个解决方案的关键在于:使用div的嵌套实现树状结构的父子关系,这样我们就可以的到某个特定节点的id号,然后利用js的方法得到内嵌于该div中的子div(节点),对他进行隐藏/显示的操作。
function hide(idnum,pic){ var parent=document.getElementById(eval(idnum));//得到父节点id号 var children=parent.getElementsByTagName("div");//遍历所有子节点div,隐藏他们 for(var i=0;i<children.length;i++){ children[i].style.display="none"; } addplusnoslib(idnum,pic);//更换节点把手,将展开的-号图片变成+号图片 }
我们还需要完成上面那个更换图片把手的方法
function addplusnoslib(idnum,pic){ pic.src="childnoslibplus.gif";//更换节点把手,将展开的-号图片变成+号图片 pic.onclick=function (){//点击+号图片展开子节点的事件 pic.src="childnoslibminus.gif";//将图片变成-号 var parent=document.getElementById(eval(idnum));//遍历所有子结点,显示他们 var children=parent.getElementsByTagName("div"); for(var i=0;i<children.length;i++){ children[i].style.visibility="true"; } pic.onclick=function hide(){//把展开子节点事件覆盖掉,变成关闭子结点事件 var parent=document.getElementById(eval(idnum)); var children=parent.getElementsByTagName("div"); for(var i=0;i<children.length;i++){ children[i].style.display="none"; } addplusnoslib(idnum,pic); }; } }
这样我们已经基本完成了对一个一层树状结构的构造了。
一条好消息和一条坏消息。好消息是:我们得到我们想要的轮子了。坏消息是:轮子是方的。
上面的方案经不起推敲
1)我们无法扩展这棵树。1个1层结构的树起不了什么作用,我们需要一个能满足目录层次更深的树。虽然我们可以再增加div的深度。但js可能无法实现复杂的循环。
2)我们不能碰他,因为这个代码非常脆弱。我们唯一可以碰的也许就是那几个带连接的名字
3.从失败走向成功
3.1从JTree得到的启发
在我们的失败的例子中已经展示了足够多的操作树的方法,而失败的主要原因是我们使用了一个方形的磨具来制造我们的轮子。因此我们需要有一个良好的磨具--MVC。我们可以看看JAVA中的JTree是如何实现树状结构的。
JTree主要用于在SWING中展示树,而模型的制作是交给DefaultTreeModel来完成的我们可以这样得到一棵JAVA的树。
DefaultMutableTreeNode root=new DefaultMutableTreeNode("China"); DefaultMutableTreeNode sh=new DefaultMutableTreeNode("Shanghai"); DefaultTreeModel model=new DefaultTreeModel(root); JTree tree=new JTree(model);
JAVA已经给我们造好了房子,我们要做的是需要搬进去住就行了。而我们现在一无所有,需要从拌水泥开始。但是我们已经拥有了一张不错的设计图纸(MVC)和熟练的制造技术(javascript方法),那还有什么可担心的呢。
3.2付诸实施
在真正动手之前,必须清醒地认识到,我们不能让dom做我们的模型。我们必须把模型从dom中分离开来,让dom作为VIEW。(失败的例子中dom担负了太多的角色)。好了我们可以开始了。
3.2.1实现node
任何树都有节点。因此我们需要一个node类。
类的属性包括:id号(用来唯一确定node),nodeName(节点名字),parentNode(父节点),childNodes(子结点数组)
status(如果节点是文件夹,用来确定是打开还是关闭),visible(是可见还是被隐藏了)
我们的node类看上去像这样:
function node(name,parent){ this.id=null; this.status=true;//文件夹是打开还是关闭状态 this.name=name; this.parent=parent;//父节点(他也是node类型) this.visible=true; this.child=new Array();//子结点数组,存放的也是node类型 this.addParent=function(parent){ if(typeof(parent)=="object"){ this.parent=parent; } } this.getParentName=function(){ if(this.parent){ return parent.name; } } this.addChild=function(value){ if(typeof(value)=="object"){ this.child.push(value); } } this.getChildNodes=function(){ return this.child; } this.hasChild=function(){ if(this.child.length>0) return true; else return false; } //。。。(现在已经具备了基本的功能,今后还需要继续完善) }
3.2.2实现treeModel
毫无疑问,一棵树的模型也是有很多树的节点组成的。我们在这个类中组装我们的node节点。
function treeMode(){ var treeMode=this; var root=new node("Ajax in Action",null);//根元素 var chapter1=new node("Chapter 1",root);//一级子类 var chapter2=new node("Chapter 2",root); var para1=new node("para1",chapter1);//二级子类 var para2=new node("para2",chapter1); var word1=new node("word1",para1);//三级子类 var alpha1=new node("alpha1",word1); word1.addChild(alpha1);//添加子结点 para1.addChild(word1); chapter1.addChild(para1); chapter2.addChild(para2); root.addChild(chapter1); root.addChild(chapter2); this.getTreeRoot=function(){ return root; }; return treeMode; //。。。(现在已经具备了基本的功能,今后还需要继续完善) }
3.2.3实现treeView
我们已经构建好了模型,接下来就是展示他。这是一个比较艰难的部分,但主要思想很简单:将node类型转换成相应的div,然后添加到body上就能呈现了。
function tree(){ var body=document.body; var treemode=new treeMode();//这里的变量treemode如果改treeMode将会出错 root=treemode.getTreeRoot(); var tree=this;//将自己赋给tree变量,方便下面的函数调用 //同时防止了this转意出现错误 //node->div每一个div有一个img描述(文件夹,文件,根目录)a标记表示节点名称 this.getDiv=function(node){ var div=document.createElement("div"); var img1=document.createElement("img"); var a=document.createElement("a"); a.href="#"; var nodename=node.name; var txtnode=document.createTextNode(nodename); a.appendChild(txtnode); if(node.parent==null){//如果没有父节点,表明这个节点是根节点,我们把图片设成根节点对应的图片 img1.src="root.gif"; } else if(node.child.length>0){//如果有子结点,那么我们需要用一个文件夹的图片描述他 var imghander=document.createElement("img");//每个文件夹前面都有一个把手,实现展开和关闭动作 if(node.status){//根据文件夹状态挑选图片,这个是表示打开的文件夹 img1.src="folderopen.gif"; imghander.src="childnoslibminus.gif"; div.appendChild(imghander); } else{ img1.src="folderclose.gif"; imghander.src="childnoslibplus.gif"; div.appendChild(imghander); } } else{//其他情况就是文件节点(叶子节点) img1.src="page.gif"; node.status=true;//其实叶子节点没有文件夹的打开和关闭状态,我们默认他为true } /* * 根据node.visible设置div的可见性 * */ if(!node.visible){ div.style.display="none"; } else{ div.visibility="true"; } div.appendChild(img1); div.appendChild(a); return div; }; //递归方法,找到treemodel中的所有节点,将他们转换成div this.getTree=function(node){ var div=this.getDiv(node);//调用上面的转换方法 body.appendChild(div); if(node.hasChild()){ var child=node.getChildNodes(); for(var i=0;i<child.length;i++){ tree.getTree(child[i]); } } } //调用一下,这样我们在调用tree()的时候就能得到树了 this.getTree(root); }
3.2.3查看结果
我们已经完成了一棵树的构造,虽然是静态的,我们可以在body中调用tree()方法得到树
你可以在构造函数中去掉一个三级节点的时候,二级节点将会自动从一个文件夹变成文件的图标!
4.继续完善
4.1实现事件
接下来我们需要让这棵树动起来,我们需要为表示把手的img提供一个onclick事件。失败的模型中,我们直接改变div的style.display或visibility属性。而这个方案中我们只是让div作树的呈现,所以我们改变策略,让事件通知我们的tremodel模型。
4.1.1实现事件的关键:ID
要让treeview和treeModel联系起来的方法是:给他们分配同一个id。前面的代码中我们并没有初始化id。我们现在需要编写一个方法,实现node.id的自动编号。
var count=0;//全局变量 function addId(node){ node.id=count; count++; if(node.hasChild()){ var children=node.getChildNodes(); for(var i=0;i<children.length;i++){ addId(children[i]);//递归遍历所有的node节点 } } }
在treeMode()函数中调用addId(root);
function treeMode(){ ....//其他省略 addId(root); }
在tree()函数内的getDiv()函数中为代表把手的图片添加和node.id相同的id号
function tree(){ ....//其他省略 this.getDiv=function(node){ var div=document.createElement("div"); var img1=document.createElement("img"); var a=document.createElement("a"); a.href="#"; var nodename=node.name; var txtnode=document.createTextNode(nodename); a.appendChild(txtnode); if(node.parent==null){ img1.src="root.gif"; } else if(node.child.length>0){ var imghander=document.createElement("img"); if(node.status){ img1.src="folderopen.gif"; imghander.src="childnoslibminus.gif"; imghander.id=node.id;//这里添加我们的id imghander.onclick=function(){//添加一个事件,这样我们可以检验一下是否正确 alert(this.id); } div.appendChild(imghander); } else{ img1.src="folderclose.gif"; imghander.src="childnoslibplus.gif"; imghander.id=node.id;//这里添加我们的id imghander.onclick=function(){//添加一个事件,这样我们可以检验一下是否正确 alert(this.id); } div.appendChild(imghander); } } else{ img1.src="page.gif"; node.status=true; //the page node has not closed or opened status } /* * set div's visibility * */ if(!node.visible){ div.style.display="none"; } else{ div.visibility="true"; } div.appendChild(img1); div.appendChild(a); divlist.push(div); return div; }; }
测试一下这段代码,正确的弹出了id号
4.1.2根据id号找node
我们已经将div中的把手图片的id号和模型中node的id号对上了,只要根据这个id号就能找到node节点对象,然后就能轻易地改变node和他子结点的属性。我们需要在treeMode中添加一个findNodeById(node,id)方法
function treeMode(){ ...//其他属性 this.clickedNode=null;//这是我们新添加的属性,用来保存findNode()的结果,方便其他函数使用。 this.findNode=function(node,id){//findNodeById()方法 var find=false; if(node.id==id&&!find){ find=true; this.clickedNode=node; } else if(node.hasChild()&&!find){ var child=node.getChildNodes(); for(var i=0;i<child.length;i++){ this.findNode(child[i],id);//递归遍历所有节点 } } } ...//其他方法 }
4.1.3实现展开/收缩方法
如果一个节点是的状态是关闭的,那么它所有的子孙节点都不可见。
但是一个节点如果是展开的,并不代表它所有的子孙节点都可见!试想一下如果1个2级文件夹试关闭的,那么打开一个1级文件夹后,2级文件夹内的文件还是不可见,因此,打开动作执行后文件的可见性只和文件夹的status(closed or opened)有关
可以看到这个方法应该作为节点的方法,所以我们在node类型中添加展开方法,而不是在树中。树的任务只需要调用一下node的setChildNodeClosed()。
function node(name,parent){ ...//其他属性 this.setChildNodeClosed=function(node){//收缩方法 var node=node; if(node.hasChild()){ var child=node.getChildNodes(); for(var i=0;i<child.length;i++){ if(child[i].visible){ child[i].visible=false; } this.setChildNodeClosed(child[i]); } } } ...//其他方法 } this.setChildNodeOpened=function(node){//打开方法 if(node.status==true){//如果文件夹的状态是打开的状态,遍历子结点,将可视性改成true,如果是关闭的,子结点不可见,我们无需动它,根据上面给出的红色提示想象一下 var child=node.getChildNodes(); for(var i=0;i<child.length;i++){ if(!child[i].visible){ child[i].visible=true; this.setChildNodeOpened(child[i]);//继续递归 } } } } }
为我们的treeMode增加一个setStatus()方法,方法内部是查找id号,然后改变一系列node的status
function treeMode(){ ...//其他属性 this.clickedNode=null;//刚才我们添加过的属性 this.findNode=function(node,id){..//我们刚才实现过了} this.changeStatus=function(id){//改变树中节点状态 this.findNode(root,id);//找节点 if(this.clickedNode){//节点找到了 if(this.clickedNode.status){ this.clickedNode.status=false;//如果文件是打开的,那关闭他 this.clickedNode.setChildNodeClosed(this.clickedNode); } else{ this.clickedNode.status=true; this.clickedNode.setChildNodeOpened(this.clickedNode); } } } ...//其他方法 }
最后在我们的onclick事件中添加这个changeStatus()方法
function tree(){ ...//省略属性 this.getDiv=function(node){ ...//省略 if(node.parent==null){ img1.src="root.gif"; } else if(node.child.length>0){ var imghander=document.createElement("img"); if(node.status){ img1.src="folderopen.gif"; imghander.src="childnoslibminus.gif"; imghander.id=node.id; imghander.onclick=function(){ var id=this.id; treemode.changeStatus(id);//调用tree模型的changeStatus() tree.getTree(root); } div.appendChild(imghander); } else{ img1.src="folderclose.gif"; imghander.src="childnoslibplus.gif"; imghander.id=node.id; imghander.onclick=function(){ var id=this.id; treemode.changeStatus(id);//调用tree模型的changeStatus() tree.getTree(root);//将我们改变状态后的模型显示出来 } div.appendChild(imghander); } } else{ ...//省略 } ...//省略设置可见性方法 }; this.getTree=function(node){ ...//省略 } this.getTree(root); }
4.1.4检验代码
运行一下代码,点击chapter1的收缩图标后,浏览器中又增加了一棵树!我知道这并不是你想要的,但我们可以观察一下新加入的树,它的确正确的关闭了文件夹!我们最后需要作的仅仅是去掉老的那个树
4.1.5刷新树
要去掉已经在网页中显示的树,就要找到对应的div,从document.body中removeChild便可。但遍历整个页面并不可行,第一页面很大的话效率降低,第二容易造成误删。解决方法是我们可以给课div树做一个快照或索引,按照索操作不就行了吗。大白话就是--做一个存放div的数组。
function tree(){ ...//其他省略 var divlist=new Array();//存放div的数组 this.getDiv=function(node){ var div=document.createElement("div"); ..//省略其他 imghander.onclick=function(){//我们的展开关闭事件 var id=this.id; treemode.changeStatus(id); tree.refreshTree(root);//刷新树方法 } divlist.push(div);//将所有新建的div都加入divlist中保管 return div; } this.refreshTree=function(root){//包装一下3个方法 this.removeTree(); this.getTree(root); this.showTree(); } this.removeTree=function(){//移除老树的方法 for(var i=0;i<divlist.length;i++){ document.body.removeChild(divlist[i]); } divlist=new Array(); } this.getTree=function(node){//这是以前写过的方法,我们把其中的body.appendChild(div);去掉 var div=this.getDiv(node); //body.appendChild(div);去掉他这个任务交给新的showTree()方法管理 if(node.hasChild()){ var child=node.getChildNodes(); for(var i=0;i<child.length;i++){ tree.getTree(child[i]); } } } this.showTree=function(){//显示新树的方法 for(var i=0;i<divlist.length;i++){ document.body.appendChild(divlist[i]); } } }
5.测试并总结
测试你的代码,不出意外你将会的到一个比较完美的树形结构,有多完美?我们可以稍微考验一下我们的程序
function treeMode(){ var treeMode=this; this.count=0; this.clickedNode=null; var root=new node("Ajax in Action",null); for(var i=0;i<100;i++){//这里就加个for循环吧 var chapter1=new node("Chapter 1",root); var chapter2=new node("Chapter 2",root); var para1=new node("para1",chapter1); var para2=new node("para2",chapter1); var word1=new node("word1",para1); var alpha1=new node("alpha1",word1); word1.addChild(alpha1); para1.addChild(word1); chapter1.addChild(para1); chapter2.addChild(para2); root.addChild(chapter1); root.addChild(chapter2); } addId(root); }
以上基本是按我如何一步步地实现这棵有点复杂的树的开发思路,JAVA 中JTree和DefaultTreeModel给与我很大的启发,使我完成了从最早的方形轮子到圆形轮子的进化过程,过程中不时遭遇到javascript语言制造的小麻烦和模型完善的困难。但完成之后也对MVC这种编程思想有了更进一步的认识。看完此文希望诸位对改变“重复发明”的偏见。
评论
9 楼
fregen
2009-02-11
楼主应该去看看jquery ui
8 楼
lijiabin102
2009-02-03
我说两句啊……
(1)这样构建的树从数据库里拉几千条数据显示的速度怎么样?这种从数据库拉出数据渲染成树的方式显示在页面上要多少秒
(2)他能不能方便的实现节点的动态增删改以及位置变化(我不是说实现拖拉),只要能动态的移动即可(比如:把一个节点(下面可能还有好多字节点)挪到另外的节点下去),动态删除和挪动的时候如何处理内存泄漏问题
以上两点如能解决,就是非常成功的树
(1)这样构建的树从数据库里拉几千条数据显示的速度怎么样?这种从数据库拉出数据渲染成树的方式显示在页面上要多少秒
(2)他能不能方便的实现节点的动态增删改以及位置变化(我不是说实现拖拉),只要能动态的移动即可(比如:把一个节点(下面可能还有好多字节点)挪到另外的节点下去),动态删除和挪动的时候如何处理内存泄漏问题
以上两点如能解决,就是非常成功的树
7 楼
gwallan
2009-02-02
不错不错,思路很清晰
6 楼
srt
2009-02-02
这是楼主的代码 我给test了一下
5 楼
hanjs
2009-01-14
lz的文章很有启发性。如果在把tree render加上就更丰富了,可以自定义每个节点的显示样式。
不知道能否提供你的所有代码,让我研究一下,谢谢!
不知道能否提供你的所有代码,让我研究一下,谢谢!
4 楼
xxrrss
2008-10-27
多谢LZ!使我对JavaScript,和树形结构的原理有了更深的了解!如果你能结合AJAX来实现数据节点的展示,就更perfact!如果你有想关的代码,请发到我邮箱:ai198742@gmail.com,谢谢!
3 楼
achun
2008-07-12
<div class='quote_title'>terrynoya 写道</div>
<div class='quote_div'>..............<br/>
感谢分享,希望能贴下js代码,php没有学过,呵呵</div>
<p>很高兴讨论,这个确实要实作一个的,我也需要用,不过因为不同应用的tree原始数据来源不同,可能方法就不会一样了.</p>
<p>这样,你先给我一个原始的数据样本,我来根据这个数据样本的结构写js.你原来帖子中的<span><span>node</span></span>函数是用来构建结构的,我要的样本是一个比如:</p>
<p>Array/Object的对象,里面的name和value表示了数据间的tree结构,</p>
<p>这样的原始数据样本.</p>
<div class='quote_div'>..............<br/>
感谢分享,希望能贴下js代码,php没有学过,呵呵</div>
<p>很高兴讨论,这个确实要实作一个的,我也需要用,不过因为不同应用的tree原始数据来源不同,可能方法就不会一样了.</p>
<p>这样,你先给我一个原始的数据样本,我来根据这个数据样本的结构写js.你原来帖子中的<span><span>node</span></span>函数是用来构建结构的,我要的样本是一个比如:</p>
<p>Array/Object的对象,里面的name和value表示了数据间的tree结构,</p>
<p>这样的原始数据样本.</p>
2 楼
terrynoya
2008-07-12
<div class='quote_title'>achun 写道</div><div class='quote_div'><p>佩服LZ的精神.<br/>不过你的代码和介绍写的太长,没有提纲,很难看明白.</p>
<p>类似你这样的问题,以前我在phpchina上也有过讨论,不过那是一个文本的php实现.</p>
<p>原理应该类似,都涉及到数组的Tree处理问题.</p>
<p>我在那个回复中有一个递归的算法,您有兴趣可以参考一下.</p>
<p> </p>
<p>原始问题</p>
<p><a href='http://www.phpchina.cn/bbs/viewthread.php?tid=60636&amp;extra=&amp;page=1&amp;sid=aD9MXb' target='_blank'>递归技术问题</a></p>
<p>我的最终代码(php的,不过可以改成js)</p>
<p><a href='http://www.phpchina.cn/bbs/viewthread.php?tid=60636&amp;extra=&amp;page=3&amp;sid=aD9MXb' target='_blank'>第三页</a></p>
<p> </p></div><br/>
感谢分享,希望能贴下js代码,php没有学过,呵呵
<p>类似你这样的问题,以前我在phpchina上也有过讨论,不过那是一个文本的php实现.</p>
<p>原理应该类似,都涉及到数组的Tree处理问题.</p>
<p>我在那个回复中有一个递归的算法,您有兴趣可以参考一下.</p>
<p> </p>
<p>原始问题</p>
<p><a href='http://www.phpchina.cn/bbs/viewthread.php?tid=60636&amp;extra=&amp;page=1&amp;sid=aD9MXb' target='_blank'>递归技术问题</a></p>
<p>我的最终代码(php的,不过可以改成js)</p>
<p><a href='http://www.phpchina.cn/bbs/viewthread.php?tid=60636&amp;extra=&amp;page=3&amp;sid=aD9MXb' target='_blank'>第三页</a></p>
<p> </p></div><br/>
感谢分享,希望能贴下js代码,php没有学过,呵呵
1 楼
achun
2008-07-12
<p>佩服LZ的精神.<br/>不过你的代码和介绍写的太长,没有提纲,很难看明白.</p>
<p>类似你这样的问题,以前我在phpchina上也有过讨论,不过那是一个文本的php实现.</p>
<p>原理应该类似,都涉及到数组的Tree处理问题.</p>
<p>我在那个回复中有一个递归的算法,您有兴趣可以参考一下.</p>
<p> </p>
<p>原始问题</p>
<p><a href='http://www.phpchina.cn/bbs/viewthread.php?tid=60636&amp;extra=&amp;page=1&amp;sid=aD9MXb' target='_blank'>递归技术问题</a></p>
<p>我的最终代码(php的,不过可以改成js)</p>
<p><a href='http://www.phpchina.cn/bbs/viewthread.php?tid=60636&amp;extra=&amp;page=3&amp;sid=aD9MXb' target='_blank'>第三页</a></p>
<p> </p>
<p>类似你这样的问题,以前我在phpchina上也有过讨论,不过那是一个文本的php实现.</p>
<p>原理应该类似,都涉及到数组的Tree处理问题.</p>
<p>我在那个回复中有一个递归的算法,您有兴趣可以参考一下.</p>
<p> </p>
<p>原始问题</p>
<p><a href='http://www.phpchina.cn/bbs/viewthread.php?tid=60636&amp;extra=&amp;page=1&amp;sid=aD9MXb' target='_blank'>递归技术问题</a></p>
<p>我的最终代码(php的,不过可以改成js)</p>
<p><a href='http://www.phpchina.cn/bbs/viewthread.php?tid=60636&amp;extra=&amp;page=3&amp;sid=aD9MXb' target='_blank'>第三页</a></p>
<p> </p>
相关推荐
总结一下,Java中根据过滤条件显示树形结构涉及的主要知识点有:树形数据结构的实现,自定义节点类,过滤逻辑的定义,以及使用Swing的`JTree`组件进行可视化展示。理解并掌握这些概念,可以帮助你有效地处理复杂的...
标题“JTree 更新版 不错的树形控件”表明这是一个经过更新优化的JTree实现,可能包含了一些增强功能或改进。 描述中提到的“treeNodes(数组形式)”是指JTree的数据模型,通常由DefaultTreeModel类处理。这个模型...
根据提供的文件信息,我们可以分析并总结出以下关于“Java实现动态改变树形结构中主节点的名称”的相关知识点: ### 一、理解树形结构 在计算机科学中,树形结构是一种常用的数据组织形式,它将数据组织成类似于树...
在Java编程中,`JTree`是Swing库中的一个组件,用于展示树形数据结构。这个组件在GUI(图形用户界面)应用中非常常见,因为它可以清晰地展示层次关系的数据,比如文件系统目录结构。在Java中动态实现二叉树,即在...
Swing实现树形结构通常涉及到JTree类、DefaultMutableTreeNode类以及TreeModel接口。下面我们将深入探讨这两个示例文件`TreeMenu2.java`和`TreeMenu.java`可能涉及的关键知识点。 1. **JTree类**: JTree是Swing中...
在本案例中,我们讨论的是一个使用JavaScript实现的JTree,这通常是通过HTML、CSS和JavaScript(可能包括jQuery或其他JavaScript库)来创建的。下面我们将深入探讨`JTree`的实现及其相关知识点。 1. **JTree基本...
jtree树形组件
Java树形结构是一种数据结构,它模仿了自然界中的树状模型,由节点(或称为顶点)和边组成。在计算机科学中,每个节点可以有零个或多个子节点,而根节点没有父节点。这种结构广泛应用于各种编程场景,如文件系统、...
`JTree2.0` 是一个基于 `JavaScript` 的目录树组件,用于构建可交互的树形菜单导航系统。这个组件在各种主流浏览器上经过了测试,确保了良好的兼容性和用户体验。在网页设计和开发中,树形结构常用于组织大量层次化...
3. **模型-视图-控制器(MVC)**:遵循MVC设计模式,将数据模型、用户界面视图和控制逻辑分离,使代码更易维护。 4. **`JTree`的使用**: - 创建`DefaultTreeModel`,定义树的结构。 - 实现`TreeNode`接口,...
`jTree`是Java Swing库中用于创建和展示树形数据结构的一个组件,它允许用户以图形化的方式查看和操作层次化的数据。本项目的核心是利用`jTree`实现一个功能,即当用户在树形结构上点击一个节点时,能够弹出一个聊天...
在给定的“java实用组件集”中,源码提供了实现树形结构组件的方法,这对于开发人员理解和构建自己的树形组件非常有帮助。以下是关于Java树形结构组件的一些关键知识点: 1. **JTree类**: Java Swing库中的`JTree`...
jtree和QQ项目\树实现好友列表,并模拟来信图片变换
JTree是一款非常实用的JavaScript实现的目录树插件,它允许开发者轻松地创建动态、可扩展的无限层级的目录树结构。对于学习和使用目录树的开发者来说,JTree是一个极具价值的工具。 **1. 功能特性** JTree具有以下...
JTree 树形菜单插件包下载,在网页上快速实现树控菜单的一个小插件,功能相对完善,本次更新功能:加入treeNodes(数组形式),通过treeNodes可以对指定的子树进行收缩和展开功能,查找指定节点的功能。加入这个功能...
它允许用户在应用程序中构建树形视图来表示目录结构、组织结构图等。`JTree`继承自`JComponent`类,并且实现了`AccessibleContext`接口。 #### 构造方法 `JTree`提供了多种构造方法以适应不同的应用场景: 1. **...
3. **模型-视图-控制器(MVC)**: `JTree`遵循MVC模式,其中`TreeModel`是模型,`JTree`是视图,而事件监听器则扮演控制器的角色。`DefaultTreeModel`是内置的模型类,可以方便地创建和管理树数据。 4. **事件处理*...
用JSplitePane将窗口划分为左右两部分。单机左边菜单,在右边串口显示显示相关性息。相关功能可自行添加。
每个节点可以包含任意数量的子节点,形成一个树形结构。 - **DefaultMutableTreeNode**:Swing提供了一个默认实现`DefaultMutableTreeNode`,支持添加、删除和修改节点操作。 - **TreeModel**:`javax.swing.tree....