zoukankan      html  css  js  c++  java
  • dTree的分析和二次开发,ajax加载dtree节点(下)(转)

    在dTree中,树中的节点是一次生成的,但在一些应用场景中,节点数非常大,比如我国的行政区划中省、市县两级的数量就超千个,一次性的生成dTree树非常耗资源,速度也慢。针对这种情况需要“异步”构建树,比如在页面上先生成省、自治区的一级节点,当用鼠标点开某个“省”节点时,实时从后台获得该省下级的市县节点。

    下面就一步步的完成这个对dTree的改造需求。

    改造原则

    我在这里要说明的是:不建议对dTree大改,因为改的越多风险越大,毕竟我们只是dTree的使用者,而不是开发者,特别在项目时间紧、压力大的环境中,迅速打造一个能用、稳定的控件尤其重要。

    创建一级节点

    这里的行政区划不规范,和国家规定的有出入,但作为示例程序比较好理解,从我所在的省份“陕西省”开始,省的下级有“陕北”、“关中”、“陕南”三个子集。

    1. d = new dTree(’d'); //创建树,名称为’d’
    2. d.add(0,-1,’陕西省’);
    3. d.add(1,0,’陕北’);
    4. d.add(2,0,’关中’);
    5. d.add(3,0,’陕南’);
    6. document.write(d);

    生成的页面显示:

    dtree03

    在dTree中,如果一个节点没有子集,它的前面不会出现“+”图标,我们希望在红色标记处形有“+”或“-”图标,这样就可以动态的从后台获取他们的子集。查看d.add()函数的实现代码:

    1. dTree.prototype.add = function(id, pid, name, url, title, target, icon, iconOpen, open) {
    2.     //增加到节点数组的末尾
    3.     this.aNodes[this.aNodes.length] = new Node(id, pid, name, url, title, target, icon, iconOpen, open);
    4. };

    在add函数中,new了一个节点对象,aNodes是dTree中的节点数组,下标“this.aNodes.length”是数组末尾的下一个,表示在数组最后增加一个节点。将上面的代码改动一下:

    1. d = new dTree(’d');
    2. d.add(0,-1,’陕西省’);
    3.  
    4. //陕北
    5. var shanbei = new Node(1,0,’<input type=\"checkbox\" name=\"where\" value=\"1\">陕北’);
    6. shanbei._hc = true; //有子节点
    7. d.aNodes[d.aNodes.length] = shanbei; //加入到树
    8. //关中
    9. var guanzhong = new Node(2,0,’<input type=\"checkbox\" name=\"where\" value=\"2\">关中’);
    10. guanzhong._hc = true;
    11. d.aNodes[d.aNodes.length] = guanzhong;
    12. //陕南
    13. var shannan = new Node(3,0,’<input type=\"checkbox\" name=\"where\" value=\"3\">陕南’);
    14. shannan._hc = true;
    15. d.aNodes[d.aNodes.length] = shannan;
    16.  
    17. document.write(d);

    先new出节点对象,将对象的”_hc”属性置为true,表示有子节点,形成的页面显示如下(手工点开了“关中”节点):

    dtree04

    点击“显示html”按钮,观察一下树的html结构:

    1. <div class="dtree">
    2.     <div class="dTreeNode">
    3.         <img id="id0" src="img/base.gif" alt="" />陕西省</a>
    4.     </div>
    5.     <div id="dd0" class="clip" style="display:block;">
    6.         <div class="dTreeNode">
    7.             <a href="javascript: d.o(1);"><img id="jd1" src="img/plus.gif" alt="" /></a>
    8.             <img id="id1" src="img/folder.gif" alt="" />
    9.             <a href="javascript: d.o(1);" class="node"><input type="checkbox" name="where"value="1">陕北</a>
    10.         </div>
    11.         <div id="dd1" class="clip" style="display:none;"></div>
    12.         <div class="dTreeNode"><a href="javascript: d.o(2);">
    13.             <img id="jd2" src="img/minus.gif" alt="" /></a>
    14.             <img id="id2" src="img/folderopen.gif" alt="" />
    15.             <a href="javascript: d.o(2);" class="node"><input type="checkbox" name="where"value="2">关中</a>
    16.         </div>
    17.         <div id="dd2" class="clip" style="display:block;"></div>
    18.         <div class="dTreeNode">
    19.             <a href="javascript: d.o(3);"><img id="jd3" src="img/plusbottom.gif" alt="" /></a>
    20.             <img id="id3" src="img/folder.gif" alt="" />
    21.             <a href="javascript: d.o(3);" class="node"><input type="checkbox" name="where"value="3">陕南</a>
    22.         </div>
    23.         <div id="dd3" class="clip" style="display:none;"></div>
    24.     </div>
    25. </div>

    “关中”有子节点div标签,<div id=”dd2″ class=”clip” style=”display:block;”></div>,但没有内部子节点内容。

    动态获取下级节点

    节点的打开和关闭是由d.o()函数控制的,下来需要对d.o()函数做点小改动,先观察o函数的原始代码(我加上了注释):

    1. //———————————
    2. // dTree对象的o()方法
    3. // 打开或关闭指定节点
    4. //  参数id: 节点ID
    5. //———————————
    6. dTree.prototype.o = function(id) {
    7.     //id对应的节点对象
    8.     var cn = this.aNodes[id];
    9.     //html变化
    10.     this.nodeStatus(!cn._io, id, cn._ls);
    11.     //open状态反转
    12.     cn._io = !cn._io;
    13.     //关闭同级别节点
    14.     if (this.config.closeSameLevel) this.closeLevel(cn);
    15.     //状态更新保存在cookies
    16.     if (this.config.useCookies) this.updateCookie();
    17. };

    下面是改动后的代码:

    1. //———————————
    2. // dTree对象的o()方法
    3. // 打开或关闭指定节点
    4. //  参数id: 节点ID
    5. //———————————
    6. dTree.prototype.o = function(id) {
    7.     //示例程序只处理“关中”的子集
    8.     if (id == 2){
    9.         //子节点标签, “关中”子节点div的id是"dd2"
    10.         var subDIV = document.getElementById("dd" + id);
    11.  
    12.         //判断子节点标签是否有内容,如果没有内容就从“后台”动态获取,
    13.         //如果有内容则跳过,这样只在第一次打开节点时获取“后台”数据。
    14.         if(subDIV != null && !subDIV.hasChildNodes())
    15.         {
    16.             //一般通过Ajax从后台获取子集信息,示例程序省略了。
    17.             //假定从后台获取“关中”的子节点信息为:
    18.             //      有两个子节点:“西安”节点id=5,有子节点;“咸阳”id=6,无子节点(叶子节点)
    19.  
    20.             //构造西安节点
    21.             var xian = new Node(5,id,’<input type=\"checkbox\" name=\"where\" value=\"5\">西 安’);
    22.             xian._hc = true; //有子节点
    23.             this.aNodes[this.aNodes.length] = xian; //加入到树
    24.  
    25.             //构造咸阳节点
    26.             var xianyang = new Node(6,id,’<input type=\"checkbox\" name=\"where\" value=\"6\">咸阳’);
    27.             xianyang._hc = false; //无子节点
    28.             this.aNodes[this.aNodes.length] = xianyang; //加入到树
    29.         }
    30.     }
    31.  
    32.     //id对应的节点对象
    33.     var cn = this.aNodes[id];
    34.     //html变化
    35.     this.nodeStatus(!cn._io, id, cn._ls);
    36.     //open状态反转
    37.     cn._io = !cn._io;
    38.     //关闭同级别节点
    39.     if (this.config.closeSameLevel) this.closeLevel(cn);
    40.     //状态更新保存在cookies
    41.     if (this.config.useCookies) this.updateCookie();
    42. };

    o函数中增加的的代码模拟了从后台获得“关中”子节点,在一般的应用中通常是通过Ajax技术来获取动态内容,Ajax的实现种类很多,所以这里只模拟而不演示具体的。

    不论从后台通过何种技术来动态获取,获取信息必须要包括:

    1. 子节点的ID
    2. 子节点的名称
    3. 子节点是否有下级

    20-28行,根据从“后台”获得的子节点信息,在树中添加“西安”和“咸阳”两个节点,但遗憾的是,点开“关中”节点时并没有出现预想的状况,和o函数修改前没什么变化。

    同步更新DOM

    点击“显示html”按钮,在alret对话框中“关中”子节点的<div>中已经出现了“西安”和“咸阳”的标签代码,页面不响应是因为dTree的实现是基于html的,而不是基于DOM的,当语句 document.write(d); 将树html输出给浏览器后,再去改变”d”的内容,浏览器是不响应的,要达到我们的目的,需要一点技巧:

    1. <html>
    2. <head>
    3. <link rel="StyleSheet" href="dtree.css" type="text/css" />
    4. <script type="text/javascript" src="dtree.js"></script>
    5. <script type="text/javascript">
    6. <!–
    7. function show()
    8. {
    9.     alert(d.toString());
    10. }
    11. //–>
    12. </script>
    13. </head>
    14. <body>
    15. <div id="mydTree">
    16. <script type="text/javascript">
    17. <!–
    18. d = new dTree(‘d’);
    19. d.add(0,-1,‘陕西省’,null,null,null,‘img/globe.gif’);
    20.  
    21. //陕北
    22. var shanbei = new Node(1,0,‘<input type=\”checkbox\” name=\”where\” value=\”1\”>陕北’);
    23. shanbei._hc = true; //有子节点
    24. d.aNodes[d.aNodes.length] = shanbei; //加入到树
    25. //关中
    26. var guanzhong = new Node(2,0,‘<input type=\”checkbox\” name=\”where\” value=\”2\”>关中’);
    27. guanzhong._hc = true;
    28. d.aNodes[d.aNodes.length] = guanzhong;
    29. //陕南
    30. var shannan = new Node(3,0,‘<input type=\”checkbox\” name=\”where\” value=\”3\”>陕南’);
    31. shannan._hc = true;
    32. d.aNodes[d.aNodes.length] = shannan;
    33.  
    34. document.write(d);
    35.  
    36. //–>
    37. </script>
    38. </div>
    39.  
    40. <input type="button" value="显示html" onclick="show()">
    41. </body>

    在dTree输出的外面包了一层div标签,就是那个 id=”mydTree” 的div标签,然后在o函数中增加一句:

    1.             ……
    2.             //构造咸阳节点
    3.             var xianyang = new Node(6,id,’<input type=\"checkbox\" name=\"where\" value=\"6\">咸阳’);
    4.             xianyang._hc = false; //无子节点
    5.             this.aNodes[this.aNodes.length] = xianyang; //加入到树
    6.            
    7.             //同步修改DOM
    8.             document.getElementById("mydTree").innerHTML = this.toString();
    9.         }
    10.     }
    11.  
    12.     //id对应的节点对象
    13.  
    14.     var cn = this.aNodes[id];
    15.     ……
    16.  

    至此,完成“异步”dTree树的改造,页面显示效果如下:

    dtree05


    以上代码,通过了Firefox3.5和IE8.0的测试。

  • 相关阅读:
    Jedis、RedisTemplate、StringRedisTemplate之间的比较
    阿里云服务器搭建DiscuzQ
    阿里云Docker加速镜像配置
    IDEA不卡配置
    Tomcat中出现"RFC 7230 and RFC 3986"错误的解决方法
    Eclipse设置保存时自动格式化代码
    VUE中v-for和v-if不能同时使用的问题
    JS中设置cookie,读取cookie,删除cookie
    JS中数组的拷贝方法
    在VSCode中开启ESLint风格审查
  • 原文地址:https://www.cnblogs.com/sishahu/p/2108199.html
Copyright © 2011-2022 走看看