要使用jquery.treeview.js,当然第一步是要把它下载下来,放入自己的工程中,然后在页面文件中引进 jquery.js,jquery.cookie.js,jquery.treeview.js,jquery.treeview.async.js四个 库文件,其中最后一个是要使用异步加载结点的时候,要用到的,我的项目中已经用到了这个功能,在初始化树的时候,只加载顶层的数据,当点击顶层结点的时 候,才会去加载下一层的结点,所有的数据都是通过ajax去后台取得到数据。 将库文件引入后,下一步就是要定义一个列表UL:如这样: <ul id="ProductTypes"> </ul> 树数据将会加载到这个UL里面 <script type="text/javascript"> $(document).ready(function(){ //alert('ready'); $("#ProductTypes").treeview({ url: "/FetchProductTypeServlet" }); //alert('ready111'); }); </script> 这里面的意思就是当文档加载完成后,向后台FetchProductTypeServlet获取数据,注意后台输出的数据必须是json格式的数据。 下一步就是后台FetchProductTypeServlet的数据输出部分了: response.setHeader("Cache-Control", "no-cache"); response.setContentType("text/json;charset=UTF-8"); try { request.setCharacterEncoding("utf-8"); } catch (UnsupportedEncodingException e1) { e1.printStackTrace(); } 要将contenttype设置为"text/json",第一次加载初始数据的时候,会向这个FetchProductTypeServlet传递一个 get参数:root=source,所以后台可以判断root参数是否是source,如果是source,则代表是第一次加载数据,如果不是 source,则root参数传递的則是树结点的id. 数据格式如下: [ { "text": "1. Pre Lunch (120 min)", "expanded": true, "classes": "important", "children": [ { "text": "1.1 The State of the Powerdome (30 min)" }, { "text": "1.2 The Future of jQuery (30 min)" }, { "text": "1.2 jQuery UI - A step to richnessy (60 min)" } ] }, { "text": "2. Lunch (60 min)" }, { "text": "3. After Lunch (120+ min)", "children": [ { "text": "3.1 jQuery Calendar Success Story (20 min)" }, { "text": "3.2 jQuery and Ruby Web Frameworks (20 min)" }, { "text": "3.3 Hey, I Can Do That! (20 min)" }, { "text": "3.4 Taconite and Form (20 min)" }, { "text": "3.5 Server-side JavaScript with jQuery and AOLserver (20 min)" }, { "text": "3.6 The Onion: How to add features without adding features (20 min)", "id": "36", "hasChildren": true }, { "text": "3.7 Visualizations with JavaScript and Canvas (20 min)" }, { "text": "3.8 ActiveDOM (20 min)" }, { "text": "3.8 Growing jQuery (20 min)" } ] } ] 格式说明:上面的1. Pre Lunch (120 min) 结点中:"expanded": true 代表这个结点下的child是展开的,children则是子结点的数据,节点3. After Lunch (120+ min)有8个子结点,其中子结点中有一个结点3.6 The Onion: How to add features without adding features (20 min),有一个id属性,同时hasChildren:true,表示其下面又有子结点,并且会向FetchProductTypeServlet传递 参数为:root=id值,具体到这里就是root=36,那么点击这个结点的时候,后台就会接收到root=36这个值,然后我们就在具体应用中,通过 数据库查询或者其它方式找到相对应的数据,然后将这些数据构造成treeview所需要的json数据,也即是上面所示格式的数据。 后台FetchProductTypeServlet代码如下: public class FetchProductTypeServlet extends HttpServlet { ProdTypeDao prodTypeDao = null; @Override public void init() throws ServletException { // TODO Auto-generated method stub prodTypeDao = new ProdTypeDao(); super.init(); } public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request,response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setHeader("Cache-Control", "no-cache"); response.setContentType("text/json;charset=UTF-8"); try { request.setCharacterEncoding("utf-8"); } catch (UnsupportedEncodingException e1) { e1.printStackTrace(); } PrintWriter out = response.getWriter(); String root = request.getParameter("root"); System.out.println("root:"+root); try { String output = generateNodeString(root); System.out.println("output======"+output); out.print(generateNodeString(root)); } catch (ActionException e) { e.printStackTrace(); RequestDispatcher rd = null; request.setAttribute("ActionException", e); rd = request.getRequestDispatcher("/common/error.jsp"); rd.forward(request, response); } out.flush(); out.close(); } private String generateNodeString(String id) throws ActionException { if(id == null){ return ""; }else if(id.equalsIgnoreCase("source")){ return generateInitTreeString(); }else{ return generateTreeChildNodeString(Integer.parseInt(id)); } } private String generateTreeChildNodeString(int typeId) throws ActionException{ int typeId_ = typeId ; Connection conn = null; //hasSubItem StringBuilder sb = new StringBuilder(); sb.append("["); ArrayList<ProdTypeBean> l; try { l = prodTypeDao.fetchSubItem(typeId_); } catch (ActionException e) { e.printStackTrace(); throw new ActionException("generateTreeChildNodeString err","generateTreeChildNodeString","generateTreeChildNodeString err"); } int i = 0; for(Iterator it = l.iterator();it.hasNext();i++){ if(i>0){ sb.append(","); } ProdTypeBean item = (ProdTypeBean)it.next(); sb.append(generateNodeString(item)); } sb.append("]"); return sb.toString(); } private String generateLinkString(ProdTypeBean item){ return "<a href='../../CommendProduct?typeId="+item.getPT_ID()+"' target='main' >"+item.getPT_NAME()+"</a>"; } private String generateNodeString(ProdTypeBean item){ StringBuilder sb = new StringBuilder(); sb.append(" {"); sb.append(" /"text/": /""+generateLinkString(item)+"/""); try { if(prodTypeDao.hasSubItem(item.getPT_ID())){ sb.append(", /"id/":/""+item.getPT_ID()+"/""); sb.append(", /"hasChildren/":true"); } } catch (ActionException e) { e.printStackTrace(); return "{}"; } sb.append(" }"); return sb.toString(); } private String generateInitTreeString() throws ActionException{ int typeId_ = 0 ; Connection conn = null; //hasSubItem StringBuilder sb = new StringBuilder(); sb.append("["); ArrayList<ProdTypeBean> l; try { l = prodTypeDao.fetchSubItem(typeId_); } catch (ActionException e) { e.printStackTrace(); throw new ActionException("generateInitTreeString err","generateInitTreeString err","generateInitTreeString err"); } int i = 0; for(Iterator it = l.iterator();it.hasNext();i++){ if(i>0){ sb.append(","); } ProdTypeBean item = (ProdTypeBean)it.next(); sb.append(generateNodeString(item)); } sb.append("]"); return sb.toString(); } }