`

z-tree实例(二)——异步加载

阅读更多

上篇的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,否则会加载失败

 

  • 大小: 81.2 KB
  • 大小: 45 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics