一.設計思想:
1.布局css+div:好處就不多說了
2.利用ajax,當點擊樹中某個節點時才生成其子節點,這樣能避免了客戶端一次性加載整棵樹,執行速度快
3.樹的生成用java控制而不是像Dtree的實現是用javascript實現,dtree實現的js代碼看了你都會頭暈,而且這種樹是一次性加載,如果你想利用異步請求(ajax)獲得一個樹,那么實現起來相當麻煩。因為異步請求后執行是在服務器端執行的,js又不能在服務器端執行。但如果數是用java實現就不一樣了,呵呵。
4.本程序實現分四層:視圖層tree.jsp,treeAction.jsp(可以在通過控制層實現);業務層com.tree.biz.TreeBiz;數據持久層用hibernate,數據庫層用mysql
二。數據設計:
很明顯,運用表內關聯是不錯的選擇,有多種實現方式,設計了個parid字段用于標識父級id(也可以通過編號來控制,01,01001,01002的形式,具體根據項目的需求來定)建庫腳本如下:
************************************數據腳本 start********************************
?
create database if not exists `template`;
USE `template`;
?
DROP TABLE IF EXISTS `tree_demo`;
CREATE TABLE `tree_demo` (
? `id` bigint(20) NOT NULL auto_increment,
? `item_num` varchar(20) default NULL,
? `item_name` varchar(50) default NULL,
? `item_parId` bigint(20) default '0',
? PRIMARY KEY? (`id`)
) TYPE=MyISAM;
?
insert into `tree_demo` values
(1,'','一級菜單1',0),
(2,'','一級菜單2',0),
(3,'','一級菜單3',0),
(4,'','一級菜單4',0),
(5,'','一級菜單5',0),
(6,'','二級菜單11',1),
(7,'','二級菜單12',1),
(8,'','二級菜單13',1),
(9,'','三級菜單121',7),
(10,'','三級菜單122',7),
(11,'','三級菜單123',7),
(12,'','三級菜單124',7),
(13,'','二級菜單21',2),
(14,'','二級菜單22',2);
*************************************數據腳本 end******************************************
三,持久層實現,我是在myeclipse6.0中實現的,所以pojo類和dao的生成很簡單,文件名是com.tree.hibernate.TreeDemo;com.tree.hibernate.TreeDemoDAO;
四,業務邏輯層:com.tree.biz.TreeBiz;代碼如下
****************************com.tree.biz.TreeBiz???? start**************************************
package com.tree.biz;
import java.util.List;
import com.tree.hibernate.TreeDemo;
import com.tree.hibernate.TreeDemoDAO;
public class TreeBiz {
?private TreeDemoDAO dao;
?public TreeBiz(){
??dao = new TreeDemoDAO() ;
?}
?public TreeDemo getTreeDemoById(Long id){
??return dao.findById(id) ;
?}
?
?public List getChlids(TreeDemo treeNode){
??List li = null ;
??li = dao.findByItemParId(treeNode!=null?treeNode.getId():0) ;
??return li ;
?}
}
*************************************com.tree.biz.TreeBiz???? end***********************************
五,視圖層
1.css的實現代碼
***********************************************tree.css??????? start*******************************
TABLE{
?border:0px;
?margin:0px;
?padding:0px;
?font-size:12px;
}
DIV{
?border:0px;
?margin:0px;
?padding:0px;?
}
.treeClass{
?height:16px;??
?width:200px;????
?font-size:12px;
}
******************************************tree.css???? end**********************************
?2.ajax.js實現
******************************************ajax.js??????? start**********************************
// JavaScript Document
var divObject ;
function createXMLHttpRequest() {
??//alert("1");
?if (window.ActiveXObject) {
??return? new ActiveXObject("Microsoft.XMLHTTP");
?} else {
??if (window.XMLHttpRequest) {
??return new XMLHttpRequest();
??}
?}
}
function sendRequest(url,showAreaId){//第1個是提交的url,第2個是定義要將服務器返回的信息顯示在哪個id域里
?var xmlHttp = createXMLHttpRequest();
?url += "&sessionId="+parseInt(Math.random()*(10000000));
?//alert(url);
?xmlHttp.onreadystatechange = function(){
??if(xmlHttp.readyState==4){
???if(xmlHttp.status==200){
????//alert(xmlHttp.responseText);
????document.getElementById(showAreaId).innerHTML=xmlHttp.responseText;
???}else{
????alert('請求的頁面異常'+xmlHttp.responseText);
????return;
???}
??}??
?};?
?
?xmlHttp.open("GET",url, false);??
?xmlHttp.send(null);
}
******************************************ajax.js??????? end***********************************
?3.tree.jsp,這個頁面用于顯示樹
******************************************tree.jsp??????start***********************************
<%@ page language="java" import="java.util.*" pageEncoding="gb2312"%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
? <head>
??? <title>純jsp 動態tree</title>
?
?<link rel="stylesheet" type="text/css" href="../../css/tree.css">
?
?<script type="text/javascript" src="../../js/ajax.js"></script>
?<script type="text/javascript">
??function treeAcion(nodeId,level){//id:父節點id ; level:節點層次
???var node = document.getElementById('child'+nodeId);?
???var varImg = document.getElementById("varImg"+nodeId);??
???if(node.style.display == "none"){
????sendRequest("treeAction.jsp?id="+nodeId+"&level="+level,"child"+nodeId);//向頁面treeAction.jsp異步請求節點的下級節點,并將下級節點顯示在id為"child"+nodeId的層里
????if(node.innerHTML != ""){??//有下級時才顯示??
?????node.style.display = "" ;
?????varImg.innerHTML="<img? src='../images/o.gif'/>" ;//更改節點前的圖片
????}????
???}else{
????node.style.display = "none" ;
????varImg.innerHTML="<img? src='../images/c.gif'/>";//更改節點前的圖片
???}???
???return false ;
??}
?</script>
? </head>
?
? <body>
??? <div id="node0" class="treeClass"><a href="#" onclick="return treeAcion('0','0')" >根接點</a></div>
??? <div id="child0" style="display:none;">??
???? ?
??? </div>
<!--這里我通過js事件來生成一級根目錄,如果想在服務器端生成這個樹,則把這段代碼換成java實現,具體參照treeAction.jsp-->
??? <script type="text/javascript">
??? ?treeAcion('0','0');
??? </script>
? </body>
</html>
******************************************tree.jsp????????? end***********************************
4.treeAction.jsp 用于生成指定節點的下級節點,可以根據需要用servlet,或struts來做控制層實現
******************************************treeAction.jsp??????start***********************************
<%@ page language="java" import="java.util.*" pageEncoding="gb2312"%>
<jsp:directive.page import="com.tree.biz.TreeBiz"/>
<jsp:directive.page import="com.tree.hibernate.TreeDemo;"/>
<%
?try{
??TreeBiz treeBiz = new TreeBiz() ;
??Long id = Long.valueOf(request.getParameter("id")) ;//父節點id
??int level = Integer.parseInt(request.getParameter("level")) ;??//父節點層次
??int curLevel = level+1 ;//計算當前節點層次
??String space = "" ;?????????????//菜單前豎虛線數目?
??for(int i= 1 ; i<curLevel ; i++){//根據級次生成豎虛線數目???
???space +="<td width='19' nowrap><img src='../images/g.gif'></td> " ;
??}??
??List<TreeDemo> liChild = treeBiz.getChlids(treeBiz.getTreeDemoById(id));//定義要取得的直屬下級列表
??for(int i=0 ; i<liChild.size() ; i++){
???TreeDemo treeNode = liChild.get(i) ;
???String imgSrc = "" ;//圖標名稱
???if(treeBiz.getChlids(treeNode).size() == 0){//不存在下級菜單
????if(i==liChild.size()-1){ //到了最后一個菜單
?????imgSrc = "e.gif" ;
????}else{
?????imgSrc = "l.gif" ;
????}????
???}else{??????????//存在下級菜單
????imgSrc = "c.gif" ;
???}
%>
???<div id="node<%=treeNode.getId()%>"? class="treeClass">
???<table cellspacing="0" cellpadding="0" align="center" border="0" height="100%" width="100%">
????<tr>
?????<%=space %>
?????<td width='19' nowrap id="varImg<%=treeNode.getId()%>"><img? src="../images/<%=imgSrc%>"/></td>
?????<td nowrap>
??????<a href="#" onclick="return treeAcion('<%=treeNode.getId()%>',<%=curLevel %>);"><%=treeNode.getItemName()%></a>
?????</td>
????</tr>
???</table>
???</div>
???<div id="child<%=treeNode.getId()%>" style="display:none;"></div><%???
??}
??
?}catch(Exception e){
??out.println("<font color='red'>出錯了:</font>"+e.getMessage());
?}
%>
******************************************treeAction.jsp????????? end*********************************
?
總結:寫一個demo因該越簡單越好,特別是實現上用視圖層加數據庫層,這樣看著也清爽些,不用在各個層之間轉來轉去,呵呵。我們還可以在這個樹上增加右鍵功能,這樣可以通過右鍵直接給指定的節點增加下級節點,效果和效率都不錯。另外asp的實現思想也一樣,兩個頁面就行。代碼量70行左右就能實現了。