JavaScript实战-JavaScript、jQuery、HTML5、Node.js实例大全(第2版)
上QQ阅读APP看书,第一时间看更新

6.2 树视图的最简化实现

根据前面的分析,本节就来完成树视图的最简化实现,同时完成树视图最基本的功能需求。

6.2.1 树视图的HTML结构和数据结构

在页面上只需要一个<div>标签作为树视图的最外层容器,让生成的树视图都放到里面,外观则另由CSS代码控制。本节目标是“最简化实现”,所以下面并没有加入外观控制之类的代码,JavaScript代码中也暂不考虑外观控制。

        <! DOCTYPE html>
        <html>
        <head>
        <title>javascript base tree</title>
        </head>
        <body>
        <div id="mytree"></div>
        </body>
        </html>
        <script src="base.js"></script>

其中base.js文件是之前用过的一些基础代码集合。树视图的每个节点通常都有一个唯一的标识符,这里将其定义为JavaScript对象的键名,它对应的父节点定义为pid,用以关联相互之间的关系,用cn表示其中文名称,用url来存储可能的链接地址。在上面的代码后追加如下数据:

        <script>
        var dic = {
            "0" : {pid:-1, cn:’本书目录’, url:'/'}
            ,"1" : {pid:0, cn:’第1 章 JavaScript 概述’, url:'/01'}
            ,"2" : {pid:0, cn:’第2 章 用JavaScript 验证表单’, url:'/02'}
            ,"11" : {pid:1, cn:'1.1 认识JavaScript', url:'#'}
            ,"12" : {pid:1, cn:'1.2 配置JavaScript 开发环境’, url:'#'}
            ,"3" : {pid:0, cn:’第3 章 JavaScript 实现的照片展示’, url:'/03'}
            ,"21" : {pid:2, cn:'2.1  最简单的表单验证 - 禁止空白的必填项目’, url:'#'}
            ,"22" : {pid:2, cn:'2.2  处理各种类型的表单元素’, url:'#'}
            ,"23" : {pid:2, cn:'2.3  输入的邮箱地址正确吗?用正则来校验复杂的格式要求
                            ', url:'#'}
            ,"24" : {pid:2, cn:'2.4  改善用户体验’, url:'#'}
            ,"31" : {pid:3, cn:'3.1  功能设计’, url:'#'}
            ,"32" : {pid:3, cn:'3.2  照片加载与定位’, url:'#'}
            ,"33" : {pid:3, cn:'3.3  响应鼠标动作’, url:'#'}
            };
        </script>

这些数据以“本书目录”结构为基础,利用JavaScript内置对象特性构建。由于数据存储可能是乱序的,这里也是乱序设置,所以接下来要对其做序列化处理。另外,在使用这些数据之前,还应该把某个节点下的子类编号先列出来,存放在节点的child数组里。

        for(var i in dic){                               //用来处理所属关系
              if(dic[i].pid ! ==undefined){            //判断是指定的pid 才处理
                  var pid = dic[i].pid;
                  if(dic[pid]){                         //判断父类是否存在
                          dic[pid].child || (dic[pid].child = []);
                                                      //判断父类有无child,无则初始化
                          dic[pid].child.push(i);    //登记到父类child 中
                  }
              }
        }

6.2.2 用递归最简化显示树

递归理论起源于哥德尔、邱奇、图灵、克莱尼和Emil Post在20世纪30年代的工作,其中克莱尼还是正则表示法的发明者。

树的显示要做的事情就是从某个节点开始,遍历其所有子节点,然后判断子节点是否还有子节点,如果有,则继续遍历子节点的子节点,如此反复,直到结束。所以这种情况只有用递归方式才能完成。

在网页中罗列数据最好的标签就是<ul>,所以同在一个父节点下的数据都应该包含在<ul>标签里,请看【范例6-1】中的最终代码。

【范例6-1 树视图的最简化实现】

    1.      <! DOCTYPE html>
    2.      <html>
    3.      <head>
    4.               <title>javascript base tree</title>
    5.      </head>
    6.      <body>
    7.               <div id="mytree"></div>
    8.      </body>
    9.      </html>
    10.             <script src="../base.js"></script>
    11.     <script>
    12.     var dic = {
    13.             "0" : {pid:-1, cn:’本书目录’, url:'/'}
    14.             , "1" : {pid:0, cn:’第1 章 JavaScript 概述’, url:'/01'}
    15.             , "2" : {pid:0, cn:’第2 章 用JavaScript 验证表单’, url:'/02'}
    16.             , "11" : {pid:1, cn:'1.1 认识JavaScript', url:'#'}
    17.             , "12" : {pid:1, cn:'1.2 配置JavaScript 开发环境’, url:'#'}
    18.             , "3" : {pid:0, cn:’第3 章 JavaScript 实现的照片展示’, url:'/03'}
    19.             , "21" : {pid:2, cn:'2.1  最简单的表单验证 - 禁止空白的必填项目’, url:'#'}
    20.            , "22" : {pid:2, cn:'2.2  处理各种类型的表单元素’, url:'#'}
    21.             , "23" : {pid:2, cn:'2.3   输入的邮箱地址正确吗?用正则来校验复杂的格式要求
                          ', url:'#'}
    22.             , "24" : {pid:2, cn:'2.4  改善用户体验’, url:'#'}
    23.             , "31" : {pid:3, cn:'3.1  功能设计’, url:'#'}
    24.             , "32" : {pid:3, cn:'3.2  照片加载与定位’, url:'#'}
    25.             , "33" : {pid:3, cn:'3.3  响应鼠标动作’, url:'#'}
    26.    }; //因为无序排列,下面必须做依赖关系处理
    27.    //这种依赖也可以由提供数据的后端来处理
    28.     for(var i in dic){
                  //用来处理所属关系
    29.             if(dic[i].pid ! ==undefined){//判断是指定的pid 才处理
    30.                    var pid = dic[i].pid;
    31.                     if(dic[pid]){         //判断父类是否存在
    32.                              dic[pid].child || (dic[pid].child = []);
                              //判断父类有无child,无则初始化
    33.                             dic[pid].child.push(i); //登记到父类child 中
    34.                      }
    35.             }
    36.     }
    37.     var z3fTree = function(el, pid){
    38.             var ul = document.createElement("ul");  //创建一个ul 元素
    39.             for(var i in dic){                   //遍历数据
    40.                    if(dic[i].pid == pid){
                          //判断节点是否都是同一个父节点,即是否是当前需要显示的节点
    41.                             var dl = dic[i]      //取得一个节点的信息
    42.                             var li=document.createElement("li"); //创建一个li 元素
    43.                              li.innerHTML = '<a href="'+dl.url+'">'+dl.cn+'</a>';
                                //拼接html
    44.                             if(dl.child && dl.child.length>0){//判断是否还有子类
    45.                                     z3fTree(li, i.toString()); //递归下去
    46.                              }
    47.                     ul.appendChild(li); //把拼装好的li 追加到ul 中去
    48.                      }else{
    49.                             continue; //继续下一个循环
    50.                    }
    51.             }
    52.             el.appendChild(ul); //插入到给定的元素中
    53.     };
    54.     z3fTree(eg.$("mytree"), -1);
    55.     </script>

第37~53行的函数z3fTree()接受两个参数,el是给定的元素,pid是指定的父节点。第一次调用时,给定元素是页面上id为mytree的<div>标签,指定父节点从-1开始。后续的递归传递进去的参数就是程序自动加进去的。把代码保存为html文件,然后在浏览器中打开,效果如图6-2所示。

图6-2 最简化的目录树视图