上篇的ztree是写死在页面里的,这篇侧重与从数据库取数据动态加载并实现异步加载。
这里的“动态加载数据”是指从数据库中取数据显示到页面,有两种方式:一种是通过请求Action返回字符串,另一种是通过AJAX从后台取数据进行加载。
这里的“异步加载数据”指开始加载树时只加载一级节点,点击某个有子节点的父节点时再请求后台加载其子节点。
需要声明的是:
1、动态加载数据用到了两个变量,flag和sign
flag:表示数据加载情况,1-一次性加载全部数据 2-只加载一级节点
sign:表示数据加载方式,1-直接跳Action进行加载 2-使用AJAX进行加载
2、数据结构采用简单模式。
3、用的SSH框架,数据库为SQL Server2005。
以下为实例流程:
1、新建Area表:
SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO SET ANSI_PADDING ON GO CREATE TABLE [dbo].[area]( [id] [int] IDENTITY(1,1) NOT NULL, [pId] [int] NULL, [name] [varchar](50) COLLATE Chinese_PRC_CI_AS NULL, [showorder] [int] NULL, [hasChildren] [int] NULL CONSTRAINT [DF_area_hasChildren] DEFAULT ((0)), CONSTRAINT [PK_area] PRIMARY KEY CLUSTERED ( [id] ASC )WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY] ) ON [PRIMARY] GO SET ANSI_PADDING OFF GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'是否有子级,1-有 0-没有,默认为0' ,@level0type=N'SCHEMA', @level0name=N'dbo', @level1type=N'TABLE', @level1name=N'area', @level2type=N'COLUMN', @level2name=N'hasChildren'
2、insert测试数据:
insert into area(pId,name,showorder,hasChildren) values(0,'河北',1,1) insert into area(pId,name,showorder,hasChildren) values(1,'石家庄',1,1) insert into area(pId,name,showorder,hasChildren) values(1,'邯郸',2,0) insert into area(pId,name,showorder,hasChildren) values(1,'保定',3,0) insert into area(pId,name,showorder,hasChildren) values(1,'沧州',4,0) insert into area(pId,name,showorder,hasChildren) values(0,'河南',2,1) insert into area(pId,name,showorder,hasChildren) values(6,'郑州',1,0) insert into area(pId,name,showorder,hasChildren) values(6,'开封',2,0) insert into area(pId,name,showorder,hasChildren) values(6,'洛阳',3,0) insert into area(pId,name,showorder,hasChildren) values(6,'南阳',4,0) insert into area(pId,name,showorder,hasChildren) values(0,'山东',3,1) insert into area(pId,name,showorder,hasChildren) values(11,'济南',1,0) insert into area(pId,name,showorder,hasChildren) values(11,'济宁',2,0) insert into area(pId,name,showorder,hasChildren) values(11,'淄博',3,0) insert into area(pId,name,showorder,hasChildren) values(11,'德州',4,0) insert into area(pId,name,showorder,hasChildren) values(0,'山西',4,1) insert into area(pId,name,showorder,hasChildren) values(16,'太原',1,0) insert into area(pId,name,showorder,hasChildren) values(16,'大同',2,0) insert into area(pId,name,showorder,hasChildren) values(16,'朔州',3,0) insert into area(pId,name,showorder,hasChildren) values(16,'阳泉',4,0) insert into area(pId,name,showorder,hasChildren) values(2,'化皮镇',1,0) insert into area(pId,name,showorder,hasChildren) values(2,'承安镇',2,0) insert into area(pId,name,showorder,hasChildren) values(2,'正莫镇',3,0)
3、添加实体类、映射文件、DAO,添加配置文件、注入等。
4、Action:
package com.wjl.action; import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts2.ServletActionContext; public class asyncAction { private AreaDAO areaDao ; /** * 加载树状结构 * @param flag:1-加载全部结构 2-加载一级菜单 * @param sign:1-使用页面加载 2-使用AJAX加载 * @return 使用Action跳转时返回all即tree字符串,all用于在struts配置文件中找相应路径,tree字符串用于页面加载 * 使用AJAX请求时,返回null * */ public String loadZtree() throws Exception{ //1、获取request对象并设置编码 HttpServletRequest request = ServletActionContext.getRequest(); request.setCharacterEncoding("UTF-8"); String treeStr=""; Integer flag=0; Integer sign=0; String returnVal = null; try{ flag = Integer.parseInt(request.getParameter("flag")); sign = Integer.parseInt(request.getParameter("sign")); List<Area> areaList=null; Area area=null; if(flag!=0 && sign!=0){ switch(flag){ case 1: areaList = areaDao.findAll();//查询全部 break; case 2: areaList = areaDao.findByHQL(" from com.wjl.action.Area where pId=0 order by showorder");//只查询一级节点 break; } if(areaList!=null && areaList.size()>0){ for(int i=0;i<areaList.size();i++){ area = areaList.get(i); treeStr += ",{id:"+area.getId()+",pId:"+area.getpId()+",name:'"+area.getName()+"'"; if(area.getpId()==0){//说明是一级节点 if(flag==1){ treeStr+=",open:true"; } } if(area.getHasChildren()==1){//说明有子级 treeStr+=",isParent:true"; } treeStr+="}"; } if(treeStr.length()>1){ treeStr = treeStr.substring(1); } } treeStr="["+treeStr+"]"; System.out.println("*********************************************************\n"+treeStr); //使用哪种方式传值 switch(sign){ case 1: request.setAttribute("treeStr", treeStr); returnVal="all"; break; case 2: HttpServletResponse response = ServletActionContext.getResponse(); response.setCharacterEncoding("UTF-8"); response.setContentType("text/html"); response.setHeader("Pragma", "No-cache"); response.setHeader("Cache-Control", "no-cache"); response.setHeader("Cache-Control", "no-store"); response.setDateHeader("Expires", 0); response.getWriter().write(treeStr); response.getWriter().flush(); response.getWriter().close(); break; } } }catch(Exception e){ e.printStackTrace(); } return returnVal; } /** * 异步加载:点击父节点时调用此方法加载下面的子节点 * @param id 父级节点的id * @return null * */ public String async() throws Exception{ //1、获取request对象并设置编码 HttpServletRequest request = ServletActionContext.getRequest(); request.setCharacterEncoding("UTF-8"); String treeStr=""; List<Area> areaList=null; Area area=null; Integer id = Integer.parseInt(request.getParameter("id"));//父级节点的id try{ if(id!=null && !id.equals("")){ areaList = areaDao.findByHQL(" from com.wjl.action.Area where pId="+id+" order by showorder"); if(areaList!=null && areaList.size()>0){ for(int i=0;i<areaList.size();i++){ area = areaList.get(i); treeStr += ",{id:"+area.getId()+",pId:"+area.getpId()+",name:'"+area.getName()+"'"; if(area.getHasChildren()==1){//说明有子级 treeStr+=",isParent:true"; } treeStr+="}"; } if(treeStr.length()>1){ treeStr = treeStr.substring(1); } } treeStr="["+treeStr+"]"; System.out.println("*********************************************************\n"+treeStr); } }catch(Exception e){ e.printStackTrace(); }finally{ HttpServletResponse response = ServletActionContext.getResponse(); response.setCharacterEncoding("UTF-8"); response.setContentType("text/html"); response.setHeader("Pragma", "No-cache"); response.setHeader("Cache-Control", "no-cache"); response.setHeader("Cache-Control", "no-store"); response.setDateHeader("Expires", 0); response.getWriter().write(treeStr); response.getWriter().flush(); response.getWriter().close(); } return null; } public AreaDAO getAreaDao() { return areaDao; } public void setAreaDao(AreaDAO areaDao) { this.areaDao = areaDao; } }
其中AreaDao中的findByHQL的方法为:
public List<Area> findByHQL(String hql){ try{ return getHibernateTemplate().find(hql); }catch (RuntimeException re) { throw re; } }
通过Action跳转方法进行加载的访问路径为:area!loadZtree.action?flag=1&sign=1(其中flag=1表示通过action方法,sign=1表示加载全部),最后返回all,对应的JSP文件为:asyncZtree.jsp
通过AJAX方式进行加载的访问路径为:z-tree/asyncZtree2.jsp
两个文件基本上相同,就是在调用方式和接收参数时有点出入。(所以,两个文件可以合并成一个)
5、页面加载:
界面结构与上篇相同,这里就粘JS吧:
<script type="text/javascript"> var setting = { //当节点有子级节点时点击父级节点会自动加载,若没有则不会调用加载方法 async: { enable: true,//设置 zTree 是否开启异步加载模式,默认值:false,若设置为true,需要async中的其他参数 url:"area!async.action",//Ajax 获取数据的 URL 地址 type:"post",//Ajax的http请求模式,有post和get,默认为post autoParam:["id=id"],//异步加载时需要自动提交父节点属性的参数(前面那个id作为key值不能修改,后面那个可以修改。当前代码表示将选定节点的ID值作为key的value值传递到后台。) //otherParam:{"otherParam":""},//Ajax 请求提交的静态参数键值对.可以用Array格式(可以为空[ ],如果有 key,则必须存在 value。 例如:[key, value])、JSON格式(直接用 JSON 格式制作键值对,例如:{ key1:value1, key2:value2 }) contentType:"application/x-www-form-urlencoded",//Ajax 提交参数的数据类型,默认值:"application/x-www-form-urlencoded",满足绝大部分请求,按照标准的 Form 格式提交参数。contentType = "application/json" 可以满足 .Net 的编程需要,按照 JSON 格式提交参数 dataType:"text",//Ajax 获取的数据类型,默认值:"text",可以满足绝大部分请求 dataFilter: filter//用于对 Ajax 返回数据进行预处理的函数,默认值为null }, data: { simpleData: { enable: true,//开启简单模式 idKey:"id", pIdKey:"pId", rootPId:0 } } }; /** *@param treeId:对应zTree的treeId,便于用户操控 *@param parentNode:进行异步加载的父节点 JSON 数据对象 *@param childNodes:异步加载获取到的数据转换后的 Array(JSON) / JSON / String 数据对象 */ function filter(treeId, parentNode, childNodes) { if (!childNodes) return null; for (var i=0, l=childNodes.length; i<l; i++) { childNodes[i].name = childNodes[i].name.replace(/\.n/g, '.'); } return childNodes; } $(document).ready(function(){ var treeNodes =${treeStr}; if(treeNodes!=null && treeNodes!=''){ $.fn.zTree.init($("#treeDemo"), setting,treeNodes); } }); </script>
使用AJAX请求时ready方法中的代码:
$(document).ready(function(){ $.post("area!loadZtree.action?flag=1&sign=2",{"times":new Date().getTime()},function(data){ if(data!=null && data!='' && data.length>0){ eval("data="+data); //因为alert出来的字符串不是object不能直接加载,所以需要先转换成JSON对象 $.fn.zTree.init($("#treeDemo"), setting,data); } }); });
6、在弄的过程中遇到的几个问题:
1、报错:SyntaxError: missing ; before statement
通过“var treeNodes ='${treeStr}';”方式取后台传过来的值时报错,
原因是:这样得到是字符串是:'..字符串....',把单引号去掉直接取值,alert出来的是object,加载时正常
2、通过跳Action和ajax取值,从后台放回的字符串都是一样的,但是在页面上接收不一样:
原因:跳Action,直接用js变量接收,注意不用加引号(即写成'${treeStr}'),会报错。alert出来应该是多个object才是对的,若是从后台返回的字符串,则会加载不成功。
ajax取值:alert出date,发现全部都是从后台返回来的字符串,若是直接加载也不会成功。通过jQuery.parseJSON方法进行转换,尽管返回的字符串没有乱码,但在转的时候就是会因为中文乱码转换失败(可以用火狐的firebug查看)。用eval("data="+data); 转化时候alert出过个object。
即如下两个情况:
alert出来的若是后台传递过来的字符串,这种情况会加载失败。
alert出来的全部都是object,则是加载成功。
总之一句话:用来加载的treeNodes, alert出来必须是全部是object,否则会加载失败。
相关推荐
1. **数据绑定**:z-tree支持动态加载和异步加载数据,可以方便地与后端服务进行交互,获取或更新树节点信息。 2. **节点操作**:包括展开、折叠、选中、取消选中、添加、删除、编辑节点等操作,提供了一整套完善的...
### z-Tree:实验经济学软件教程 #### 一、关于z-Tree z-Tree(Zurich Toolbox for Readymade Economic Experiments)是一款由瑞士研发的实验经济学专用软件,旨在为经济实验提供一个灵活且功能强大的平台。该软件...
- `$.fn.zTree`: jQuery扩展方法,用于对`z-tree`实例的操作。 - `zTreeObj`: `z-tree`实例对象,通过该对象可以调用所有API。 5. **Demo分析** - **基本示例**: 展示了最简单的`z-tree`使用方式,包括静态数据...
`el-tree-selected-tree` 描述的就是这样一个功能,它实现了在主`el-tree`之外,单独拉出一个展示已选中节点的树,并支持在该树上删除选中节点。 首先,我们需要理解`el-tree`的基本用法。`el-tree`通过`data`属性...
2. **静态和Ajax异步加载**:z-tree支持静态加载所有节点数据,即在页面加载时一次性获取所有节点信息。此外,它还允许使用Ajax异步加载,这意味着当用户展开一个节点时,仅加载该节点及其子节点的数据,显著提高了...
"z-tree-demo"工具是一个基于JavaScript实现的树形控件,主要用于前端开发中展示层级结构的数据。这个工具以其灵活性、可定制性和易于使用的特性而受到开发者欢迎。在Web应用中,z-tree常用于构建文件系统、组织架构...
2. **数据驱动**:z-tree支持JSON数据格式,可以方便地与后台数据接口进行交互,动态加载和更新树节点,适应大数据量和实时更新的需求。 3. **事件系统**:它内置了丰富的事件机制,如点击、双击、拖拽等,开发者...
使用z-tree时,首先需要在HTML中引入相应的JS和CSS文件,然后配置JSON数据,最后初始化z-tree实例。例如: ```html <link rel="stylesheet" href="z-tree.css"> <script src="z-tree.js"> ``` ```javascript var ...
5. 实例化与数据绑定:通过Vue组件的data属性返回一个对象,该对象包含初始化树形数据(treeData)和定义展开节点id的数组(treeExpandData)。在组件的created钩子中进行数据获取和设置默认展开节点的逻辑。 6. ...
实际上,el-tree-transfer 依赖的 element-ui 组件分别是Checkbox 多选框,Button 按钮,和最主要的Tree 树形控件写成!并非是在 element-ui 的穿梭框组件上的扩展,而仅仅是参照了其外观样式和功能。
2. i-Tree Streets:此工具专注于生态服务及城市行道树的群体结构,使用样本或普查数据量化每棵树的年度环境与美学效益,并将其以美元价值计算,这些效益包括节能、改善空气质量、减少二氧化碳、雨水控制以及房地价...
Z-Tree是一款基于JavaScript的树形控件,专为Web应用程序设计,用于展示层次结构的数据,例如目录、组织结构或者文件系统。在这个压缩包中,包含的是Z-Tree运行所必需的JavaScript和CSS文件,以及一个jQuery的版本。...
KD-Tree 开源实现以及 OpenCV KD-Tree 使用
这可能涉及到理解z-tree的底层逻辑,包括如何渲染节点、处理用户交互、以及如何动态加载和更新数据。 模仿"IMO办公软件"的右键菜单,表明开发者想在z-tree节点上添加上下文菜单功能,使得用户可以通过鼠标右键点击...
需要注意的是,为了实现动态添加节点,layui.tree 组件可能需要支持动态加载或自定义渲染功能。这意味着在初始渲染树形结构时,可能需要设置 `expand` 参数以允许后续的节点添加和展开。 总结来说,这个示例展示了...
动态加载(也称为懒加载)是一种优化性能的技术,只在用户需要时才加载数据,而不是一次性加载所有数据,这对于处理大量数据或层级结构尤其有用,可以显著提升页面加载速度和用户体验。 本项目在官方Bootstrap ...
通过实践和调试,你可以根据自己的需求进行调整,例如增加异步加载数据的支持,或者与其他前端框架(如React、Vue等)集成。 总之,"基于z-tree树形结构的多级下拉选择列表"是一种实用的UI设计模式,它将复杂的树状...
bootstrap-table-tree.js对bootstrap-table中某些方法进行重写。
Ext-tree加载Ext-tree加载Ext-tree加载Ext-tree加载Ext-tree加载Ext-tree加载Ext-tree加载Ext-tree加载Ext-tree加载Ext-tree加载Ext-tree加载Ext-tree加载Ext-tree加载