网上找到的用UL列表做的树,都没有连接线。如果把虚线作为ul的的背景,就可以做成有连线的ul树,显示效果和梅花雪的树一样。效果在这:http://mz.host.dxsidc.com/下面是我做的树,定义树的结构用xml文件,动态增加节点也用xml。
和梅花雪的对比了一下,初始化的速度慢了好多。xmldom的速度慢是个大原因,但除了这一部分,运行的时间还是比梅花雪的要多(我的也是参考梅花雪的异步显示,第一次只显示第一级节点,其他的点击展开时再生成html)。
看来还是有差距。哪位高手给指点指点,再提高一下速度。//mytree.js
function MyTree(treename)
{
  if(typeof(treename) != "string" || treename == "") throw(new Error(-1, '没有定义树的名字!'));
  this.link     = "#";
  this.target   = "_self";
  this.imgpath  = "image/";
  this.xmlfile  = "xmltree.xml";
  this.name     = treename;
  this.current  = "";
  this.node     = {};
  this.node["root"] = {"childnodes":[]};
  this.sty='<style>.MyTree {font-size:12px;} .MyTree ul {padding-left:0px!important; padding-left:0px; margin-left:0px!important; margin-left:0px; background-image:url("'+this.imgpath+'back.gif"); background-repeat: repeat-y;} .MyTree ul.nobg {background-position:-10px;} .MyTree ul li {list-style:none; padding-left:20px;}.MyTree ul li.first{padding-left:0px;} .MyTree A {outline: none; PADDING-RIGHT: 3px; PADDING-LEFT: 3px; PADDING-TOP: 3px; PADDING-BOTTOM: 1px; color: #000060; TEXT-DECORATION: none} .MyTree A:hover {background: #7386ba; color: #fff; TEXT-DECORATION: none}</style>';  this.createXMLDOM = function()
  {
var xmldom;
if (window.ActiveXObject)
  { var ActiveX = new Array("MSXML2.DOMDocument.5.0","MSXML2.DOMDocument.4.0","MSXML2.DOMDocument.3.0","MSXML2.DOMDocument","Microsoft.XMLDOM","MSXML.DOMDocument");
for(var i=0;i<ActiveX.length;i++)
  { try{ xmldom = new ActiveXObject(ActiveX[i]);break;}catch(e){} }
  }
else
  { if (document.implementation && document.implementation.createDocument)
  { var xmldom = document.implementation.createDocument("","doc",null);}
  }
xmldom.async = false;
xmldom.resolveExternals = false;
xmldom.validateOnParse = false;
xmldom.preserveWhiteSpace = true;
return xmldom;
  };  this.loadXML = function(xml)
  {
    var ie = (window.ActiveXObject)?true:false, flag=false;
    var obj = this.createXMLDOM();
if(xml==null || xml=='') flag=obj.load(this.xmlfile); else { //没有参数,就从文件读xml
  if(ie) flag=obj.loadXML(xml); else {
var oParser=new DOMParser();
var obj=oParser.parseFromString(xml,"text/xml");
flag=true;
}} if (flag)
{ var nodes=obj.getElementsByTagName('node');
  if (nodes != null && nodes.length > 0)
  { var id='',pid='';
    for(var i=0;i<nodes.length;i++)
{ id=nodes[i].getAttribute('id');
  pid=nodes[i].getAttribute('pid');
  if(typeof(this.node[pid])=="undefined") continue;//xml中如果子节点出现在母节点前,这个子节点将被忽略
  this.node[id]=
{ "id":id,
  "pid":pid,
  "name":nodes[i].getAttribute('name'),
  "isload":false
  //"childnodes":[]
};
  if(nodes[i].getAttribute('link')!=null) this.node[id].link=nodes[i].getAttribute('link');
  if(nodes[i].getAttribute('target')!=null) this.node[id].target=nodes[i].getAttribute('target');
  if(nodes[i].getAttribute('icon')!=null) this.node[id].icon=nodes[i].getAttribute('icon'); 
  if(nodes[i].getAttribute('method')!=null) this.node[id].method=nodes[i].getAttribute('method');
  if(typeof(this.node[pid].childnodes)=="undefined") this.node[pid].childnodes=[];
  this.node[pid].childnodes[this.node[pid].childnodes.length]=this.node[id];
}
  } else alert('No Valid treeNode!');
} else alert('XML Data Load Error!');
obj=null;
  };  this.buildchild = function(id,end)
  {
var ohtml='',icon1='',icon2='';
var classname=(end==true)?' class="nobg"':'';
if(typeof(this.node[id].childnodes)=="undefined") return ohtml; var cn=this.node[id].childnodes;
if(cn.length>0)
{
  ohtml='<SPAN style="display:none;"><UL'+ classname +'>';
  for(var i=0;i<cn.length;i++)
  { if(typeof(cn[i].childnodes)=="undefined") {icon1=((i==cn.length-1)?'l2.gif':'l1.gif');icon2=(typeof(cn[i].icon)=="undefined")?'file.gif':cn[i].icon;} else {icon1=((i==cn.length-1)?'p2.gif':'p1.gif');icon2='folder.gif';}
    ohtml+='<LI id="mytree_' + cn[i].id + '"><SPAN onclick="'+ this.name +'.clickhandle('+ cn[i].id +',event);"><IMG align=absmiddle src="'+ this.imgpath + icon1 +'"><IMG align=absmiddle src="'+ this.imgpath + icon2 +'"><A  hidefocus onfocus="'+ this.name +'.focusid('+ cn[i].id +')" href="'+ ((typeof(cn[i].link)=="undefined")?this.link:cn[i].link) +'" target="'+ ((typeof(cn[i].target)=="undefined")?this.target:cn[i].target) +'">'+ cn[i].name +'</a></SPAN></LI>';
  }
  ohtml+='</UL></SPAN>';
  this.node[id].isload=true;
}
return ohtml;
  };  this.tostring = function(dynamic)
  {
   if(dynamic!=true) this.loadXML();
var ohtml='',icon1='',icon2='';
var cn=this.node["root"].childnodes;
if(cn.length>0)
{ ohtml='<SPAN onclick="'+ this.name +'.clickhandle('+cn[0].id+',event);"><IMG align=absmiddle src="'+ this.imgpath + ((typeof(cn[0].icon)=="undefined")?'root.gif':cn[0].icon)+ '"><A  style="color:#ffffff; background:#0A246A;" hidefocus onfocus="'+ this.name +'.focusid('+ cn[0].id +')" href="'+ ((cn[0].link==null)?this.link:cn[0].link) +'" target="'+ ((cn[0].target==null)?this.target:cn[0].target) +'">'+ cn[0].name +'</A></SPAN><SPAN><UL class="nobg" style="margin-top:0px;">';//顶层节点,只取第一个
  this.current=cn[0].id;   if(typeof(cn[0].childnodes)!="undefined")
  { cn[0].isload=true;
    cn=cn[0].childnodes;
for(var i=0;i<cn.length;i++)
{ if(typeof(cn[i].childnodes)=="undefined") {icon1=((i==cn.length-1)?'l2.gif':'l1.gif');icon2=(typeof(cn[i].icon)=="undefined")?'file.gif':cn[i].icon;} else {icon1=((i==cn.length-1)?'p2.gif':'p1.gif');icon2='folder.gif';}
      ohtml+='<LI class="first" id="mytree_' + cn[i].id + '"><SPAN onclick="'+ this.name +'.clickhandle('+ cn[i].id +',event);"><IMG align=absmiddle src="'+ this.imgpath + icon1 +'"><IMG align=absmiddle src="'+ this.imgpath + icon2 +'"><A hidefocus onfocus="'+ this.name +'.focusid('+ cn[i].id +')" href="'+ ((typeof(cn[i].link)=="undefined")?this.link:cn[i].link) +'" target="'+ ((typeof(cn[i].target)=="undefined")?this.target:cn[i].target) +'">'+ cn[i].name +'</a></SPAN></LI>';
}
  }
  ohtml+='</UL></SPAN>';
} if(dynamic==true) return ohtml;
return '<DIV class="MyTree" id="mytree_'+this.node['root'].childnodes[0].id+'">'+ohtml+'</DIV>'+this.sty;
  };

解决方案 »

  1.   

    操,帖子内容太长?
      this.clickhandle = function(id,e)
      { e = window.event || e; e = e.srcElement || e.target;
    if(e.tagName=="A") {if(typeof(this.node[id].method)!="undefined") eval(this.node[id].method);}
    else this.expand(id);
      };  this.expand = function(id)
      { var pid=this.node[id].pid,span;
        if(document.getElementById("mytree_"+id)==null) this.expand(pid); else
      { while(pid!='root')
      { span=document.getElementById("mytree_"+pid).childNodes;
    span=span[span.length-1];
    if(span.style.display=="none") {this.expand(pid);}
    pid=this.node[pid].pid;
      }
      }
    if(typeof(this.node[id].childnodes)!="undefined" && this.node[id].childnodes.length>0) //有子节点
      { if(!this.node[id].isload)//如果还没有生成子节点
      { var tmp=this.node[this.node[id].pid].childnodes;
    var flag=(tmp[tmp.length-1]==this.node[id]);
    document.getElementById("mytree_"+id).innerHTML+=this.buildchild(id,flag);
      }
      }
    span=document.getElementById("mytree_"+id).childNodes;
    var a=span[0].childNodes; a=a[a.length-1]; if(a) a.focus();
    if(typeof(span[1])!="undefined" && span[1].nodeType==1)
      { var s1='',s2='';
    if((span[1].style.display=="")) {span[1].style.display="none";s1='p';s2='folder.gif';} else {span[1].style.display="";s1='m';s2='folderopen.gif';}
    if(id!=this.node['root'].childnodes[0].id) {var img=span[0].childNodes[0].src;img=s1+img.substr(img.indexOf('.gif')-1,5);span[0].childNodes[0].src=this.imgpath+img;span[0].childNodes[1].src=this.imgpath+s2;}
      }
      };  this.focusid = function(id)
      { if(id==this.current) return;
        var a=document.getElementById("mytree_"+id).childNodes[0].childNodes; a=a[a.length-1];
    with(a.style){color = "#ffffff"; backgroundColor = "#0A246A";}
    a=document.getElementById("mytree_"+this.current).childNodes[0].childNodes; a=a[a.length-1];
    with(a.style){color = "#000060"; backgroundColor = "";}
    this.current = id;
      };  this.dynamicaddchild = function(url,id) //动态增加子节点,url地址返回包含子节点信息的xml文件,id是母节点
      { this.expand(id);
      if(this.node[id].isload){var tmp=document.getElementById("mytree_"+id).childNodes[1];tmp.parentNode.removeChild(tmp);}
    var tmp=this.node[this.node[id].pid].childnodes;
    var flag=(tmp[tmp.length-1]==this.node[id]);
      var span=document.getElementById("mytree_"+id).childNodes;
      span[0].childNodes[0].src=this.imgpath+((flag)?'P2':'P1')+'.gif';
      span[0].childNodes[1].src=this.imgpath+'loading.gif'; var TREE=this.name;    try{
      if(window.ActiveXObject){
    for(var i=5; i; i--){
      try{if(i==2){ xmlhttp_req = new ActiveXObject("Microsoft.XMLHTTP");}
    else{
      xmlhttp_req = new ActiveXObject( "Msxml2.XMLHTTP." + i + ".0" );
      xmlhttp_req.setRequestHeader("Content-Type","text/html");
      xmlhttp_req.setRequestHeader("Charset","utf-8");
    } break;
      } catch(e){xmlhttp_req = false;}
    }
      } else if(window.XMLHttpRequest){ 
    xmlhttp_req = new XMLHttpRequest();
    if(xmlhttp_req.overrideMimeType) {xmlhttp_req.overrideMimeType('text/html');}
      }
    } catch(e){alert("cann't build xmlhttp!");return;} xmlhttp_req.open('GET', url, true);
    xmlhttp_req.setRequestHeader('If-Modified-Since', '0');
    xmlhttp_req.setRequestHeader('CONTENT-TYPE','application/x-www-form-urlencoded');
    xmlhttp_req.send(null);
    xmlhttp_req.onreadystatechange = function()
    { if (xmlhttp_req.readyState == 4 && xmlhttp_req.status==200)
      { alert(xmlhttp_req.responseText);
    if(eval(TREE).node[id].isload) eval(TREE).clearchildload(id);
    eval(TREE).loadXML(xmlhttp_req.responseText);
    if(eval(TREE).node[id].pid=='root'){document.getElementById("mytree_"+id).innerHTML=eval(TREE).tostring(true);}
    else
    { document.getElementById("mytree_"+id).innerHTML+=eval(TREE).buildchild(id,flag);
      eval(TREE).expand(id);
    }
      }
    }
      };  this.clearchildload = function(id)
      { if(typeof(this.node[id].childnodes)!="undefined")
      { var i,tmp=this.node[id].childnodes;
    for(var i=0;i<tmp.length;i++)if(tmp[i].isload){this.clearchildload(tmp[i].id);tmp[i].isload=false;}
      }
      };}
      

  2.   


    //xmltree.xml<?xml version="1.0" encoding="utf-8"?><!--
    node 为树的一个节点,具有以下属性
    id: 编号 (必须)
    name: 名称 (必须)
    link: 连接 (可选)
    target: 目标 (可选)
    icon: 图标 (可选)
    -->
    <nodes>
    <node id="1" pid="root" name="孟州市" link="javascript:void(0);" method="alert('this maybe do other things');"/>
    <node id="2" pid="1" name="大定办事处" link="javascript:void(0);"/>
    <node id="3" pid="1" name="会昌办事处" link="javascript:void(0);"/>
    <node id="4" pid="1" name="河雍办事处" link="javascript:void(0);"/>
    <node id="5" pid="1" name="河阳办事处" link="javascript:void(0);"/>
    <node id="6" pid="1" name="化工镇" link="javascript:void(0);"/>
    <node id="7" pid="1" name="南庄镇" link="javascript:void(0);"/>
    <node id="8" pid="1" name="城伯镇" link="javascript:void(0);"/>
    <node id="9" pid="1" name="谷旦镇" link="javascript:void(0);"/>
    <node id="10" pid="1" name="赵和镇" link="javascript:void(0);"/>
    <node id="11" pid="1" name="槐树乡" link="javascript:void(0);"/>
    <node id="12" pid="1" name="西虢镇" link="javascript:void(0);"/>
    <node id="201" pid="2" name="北街" link="#?id=1" target="_blank"/>
    <node id="202" pid="2" name="北开义" link="#?id=2" target="_blank"/>
    <node id="203" pid="2" name="陈湾" link="#?id=3" target="_blank"/>
    <node id="204" pid="2" name="东关" link="#?id=4" target="_blank"/>
    <node id="205" pid="2" name="东韩" link="#?id=5" target="_blank"/>
    <node id="206" pid="2" name="东街" link="#?id=6" target="_blank"/>
    <node id="301" pid="3" name="北韩庄" link="#?id=20" target="_blank"/>
    <node id="302" pid="3" name="大宋庄" link="#?id=21" target="_blank"/>
    <node id="319" pid="3" name="张厚" link="#?id=38" target="_blank"/>
    <node id="320" pid="3" name="中曹" link="#?id=39" target="_blank"/>
    <node id="321" pid="3" name="竹园" link="#?id=40" target="_blank"/>
    <node id="401" pid="4" name="陈庄" link="#?id=41" target="_blank"/>
    <node id="402" pid="4" name="东田丈" link="#?id=42" target="_blank"/>
    <node id="403" pid="4" name="富村" link="#?id=43" target="_blank"/>
    <node id="404" pid="4" name="关耿唐" link="#?id=44" target="_blank"/>
    <node id="405" pid="4" name="兰窑" link="#?id=45" target="_blank"/>
    <node id="515" pid="5" name="西葛" link="#?id=69" target="_blank"/>
    <node id="516" pid="5" name="中龙" link="#?id=70" target="_blank"/>
    <node id="517" pid="5" name="中逯" link="#?id=71" target="_blank"/>
    <node id="601" pid="6" name="晁庄" link="#?id=72" target="_blank"/>
    <node id="602" pid="6" name="东光" link="#?id=73" target="_blank"/>
    <node id="603" pid="6" name="东孟" link="#?id=74" target="_blank"/>
    <node id="604" pid="6" name="杜庄" link="#?id=75" target="_blank"/>
    <node id="605" pid="6" name="段庄" link="#?id=76" target="_blank"/>
    </nodes>//treeTest.htm<html>
    <haed>
    <META http-equiv=Content-Type content="text/html; charset=utf-8">
    <script language="JavaScript" src="mytree.js"></script>
    </head>
    <body bgcolor=#e1e1e1><p><input type=button onclick="dy_add();" value="动态加入"><input type=button onclick="alert(document.getElementById('t').innerHTML);" value="html"><p>
    <div id="t"></div><SCRIPT language="JavaScript">
    //var dat1= new Date();var tree = new MyTree("tree");
    document.getElementById("t").innerHTML=tree.tostring();//使用比较简单,定义树的名字,调用tostring就行了
    //var dat2= new Date();
    //alert(dat2.getTime()-dat1.getTime());
    //速度不是很理想,比梅花雪的慢了快一个数量级。除下xmldom慢的部分,运行时间还是比梅花雪的多。看来还需要改进function dy_add()
    {
    var xmlurl='http://localhost/testxml.xml';
    tree.dynamicaddchild(xmlurl,'206');
    }
    </SCRIPT>
    </body>
    </html>
      

  3.   

    建议一下,尽量避免大量使用innerHTML+=,用appendChild,window.document.createElement之类的东西创建你的HTML对象
    查查document.createDocumentFragment()的用法。以上会让你的代码快上一点吧。嗯,我认为应该是的。