树形列表(菜单)在Web应用中十分常见,通常应用于目录式结构,例如产品分类、部门机构等。传统的树形菜单主要有两种加载方式:一种是一次性加载全部数据,另一种是根据用户操作逐步加载数据,但是需要刷新页面。前者加载速度较慢,并且存在大量数据没有被使用的浪费情形。后者可以逐步加载,但是频繁地刷新页面在给用户带来不便的同时,也增加了系统开发的复杂度。
当前使用的Ajax技术,同时兼顾了两种传统方式的优点,即无刷新和动态加载特性。从用户体验到服务器负担来讲都是有利的。
由于编写一个动态树形列表要考虑的问题很多,在进入正式的讲解之前,先以一个简单的页面展示一下树形列表的基本原理。了解了基本原理后,再深入研究树形列表的细节就容易多了。图1.6所示是基本原理演示页面的运行效果。 动态树形列表的基本原理是:每当单击一个子项时,动态地在子项节点内追加新的节点,同时依靠样式表设置新节点的缩进。由于新节点在父节点内追加,因此缩进效果也建立在父节点已有的缩进基础上。通过叠加的缩进使得整个列表具有了树形结构。图1.7所示是各函数之间的调用关系。 图1.6 基本原理演示页运行效果 图1.7 基本原理演示页函数调用关系 样式的缩进写法为margin-left:10px,表示左边距为10像素。为了表示节点的动态性,增加一个计数器变量counter,用于为每个新创建的子项进行编号。在响应onclick事件时,由于新的子项是包含在父节点内的,所以onclick事件会冒泡响应。为了避免出现这种情况造成创建出多余的子项,通过设置event.cancelBubble = true阻止事件冒泡。这种阻止方式仅适用于IE浏览器,在正式的树形列表中,使用了其他方式避免此问题的发生。下面是基本原理演示页面的详细代码。 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <meta http-equiv="Content-type" content="text/html; charset=utf-8"> <title>动态树形列表基本原理演示</title> <style> /* 设置class属性为item的div缩进10px */ div.item { margin-left:10px; } </style> <script type="text/javascript"> var counter = 1; //全局子项计数器 //页面加载后立即执行的方法,在menu节点增加3个子项 function init() { var menu = document.getElementById("menu"); addChildren(menu); } //在传入的pNode节点内追加3个子项 function addChildren(pNode) { event.cancelBubble = true; //阻止事件冒泡,避免父层div响应onclick事件 pNode.appendChild(createNewItem()); pNode.appendChild(createNewItem()); pNode.appendChild(createNewItem()); } //创建新的子项 function createNewItem() { var _node = document.createElement("div"); //创建1个div节点 //给新建的div节点增加内容,并设置单击后调用addChildren函数 _node.innerHTML = "<div class='item' onclick='addChildren(this)'>item" + counter + "</div>"; counter++; //计数器加1 return _node; } </script> </head> <body onload="init()"> <div id="menu"></div> </body> </html>