jQuery Easyui Tree组件

前言

Tree组件的话来做权限方面的很好,基于树组件的话分为两种,静态树和动态树,静态树的话代码比较冗余死板,动态树配合ajax+json实现从数据库调用显示方便灵活。

动态树

使用树控件先定义一个空ul元素中并使用Javascript加载数据。

<ul id="tt"></ul>  
  • 创建js文件进行json数据加载
$('#tt').tree({    
    url:'tree_data.json'   
}); 
  • 使用树组件就要遵循别人提供的规则。

在这里插入图片描述

  • 因为是基于动态树案例要进行数据库访问所以配合自定义mvc框架我们必须导入依赖架包。

在这里插入图片描述

思路和流程

首先我们的菜单栏是存储在数据库中的,我们要配合mvc框架+ajax实现数据渲染,关键点在于menuid和parentid字段,这里就涉及到了权限的方面,在java代码中可以根据menuid来逻辑进行权限的控制,比如有的人可以看到所有菜单,有的只能看到部分菜单具体请往下看。
在这里插入图片描述
简单的权限关系理解,这里简单的画一下。
在这里插入图片描述

前端步骤:

(1)前端导入软件包。
(2)引入css样式
(3)引入图标样式
(4)引入jquery,因为easyui的核心库是基于jQuery的
(5)引入easyui的核心js库
(6)自定义js文件并引入,主要提供访问路径执行数据访问层进行数据渲染

后端流程概述:
在这里插入图片描述

代码实现案例

  • index界面文件引入的顺序,以及隐藏域的传值需要注意。
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>

<script type="text/javascript"
	src="${pageContext.request.contextPath }/static/js/index.js"></script>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>主界面</title>

<!--全局样式  -->
<link rel="stylesheet" type="text/css"
	href="${pageContext.request.contextPath }/static/js/jquery-easyui-1.5.1/themes/default/easyui.css">
<!--定义图标  -->
<link rel="stylesheet" type="text/css"
	href="${pageContext.request.contextPath }/static/js/jquery-easyui-1.5.1/themes/default/easyui.css">
<script type="text/javascript"
	src="${pageContext.request.contextPath }/static/js/jquery-easyui-1.5.1/jquery.min.js"></script>
<!--组件库源码的js文件  -->
<script type="text/javascript"
	src="${pageContext.request.contextPath }/static/js/jquery-easyui-1.5.1/jquery.easyui.min.js"></script>
<!-- 自定义 js-->
<script type="text/javascript"
	src="${pageContext.request.contextPath }/static/js/index.js"></script>

</head>
<body class="easyui-layout">
	<input type="hidden" id="ctx"value="${pageContext.request.contextPath }">
		
	<!-- 头部 -->
	<div data-options="region:'north',border:false"
		style="height: 60px; background: #B3DFDA; padding: 10px">管理系统</div>
	<!-- 菜单管理 -->
	<div data-options="region:'west',split:true,title:'West'"
		style="width: 150px; padding: 10px;">
		<ul id="tt"></ul>
	</div>
	<!-- 内容块 -->
	<div
		data-options="region:'east',split:true,collapsed:true,title:'East'"
		style="width: 100px; padding: 10px;">east region</div>
	<!-- 底部权限 -->
	<div data-options="region:'south',border:false"
		style="height: 50px; background: #A9FACD; padding: 10px;">south
		region</div>
	<div data-options="region:'center',title:'Center'"></div>
</body>
</html>
  • 自定义的js文件提供jquery加载的资源路径。
$(function(){
	$('#tt').tree({
		//这是请求路径
		url:$("#ctx" ).val()+'/menu.action?methodName=menuNodes' 
	});
})
  • TreeVo树格式的实体类提供json数据格式的转载。
  package com.liyingdong.vo;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;


public class TreeVo<T> {
	/**
	 * 节点ID
	 */
	private String id;
	/**
	 * 显示节点文本
	 */
	private String text;
	/**
	 * 节点状态,open closed
	 */
	private Map<String, Object> state;
	/**
	 * 节点是否被选中 true false
	 */
	private boolean checked = false;
	/**
	 * 节点属性
	 */
	private Map<String, Object> attributes;

	/**
	 * 节点的子节点
	 */
	private List<TreeVo<T>> children = new ArrayList<TreeVo<T>>();

	/**
	 * 父ID
	 */
	private String parentId;
	/**
	 * 是否有父节点
	 */
	private boolean hasParent = false;
	/**
	 * 是否有子节点
	 */
	private boolean hasChildren = false;

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getText() {
		return text;
	}

	public void setText(String text) {
		this.text = text;
	}

	public Map<String, Object> getState() {
		return state;
	}

	public void setState(Map<String, Object> state) {
		this.state = state;
	}

	public boolean isChecked() {
		return checked;
	}

	public void setChecked(boolean checked) {
		this.checked = checked;
	}

	public Map<String, Object> getAttributes() {
		return attributes;
	}

	public void setAttributes(Map<String, Object> attributes) {
		this.attributes = attributes;
	}

	public List<TreeVo<T>> getChildren() {
		return children;
	}

	public void setChildren(List<TreeVo<T>> children) {
		this.children = children;
	}

	public boolean isHasParent() {
		return hasParent;
	}

	public void setHasParent(boolean isParent) {
		this.hasParent = isParent;
	}

	public boolean isHasChildren() {
		return hasChildren;
	}

	public void setChildren(boolean isChildren) {
		this.hasChildren = isChildren;
	}

	public String getParentId() {
		return parentId;
	}

	public void setParentId(String parentId) {
		this.parentId = parentId;
	}

	public TreeVo(String id, String text, Map<String, Object> state, boolean checked, Map<String, Object> attributes,
                  List<TreeVo<T>> children, boolean isParent, boolean isChildren, String parentID) {
		super();
		this.id = id;
		this.text = text;
		this.state = state;
		this.checked = checked;
		this.attributes = attributes;
		this.children = children;
		this.hasParent = isParent;
		this.hasChildren = isChildren;
		this.parentId = parentID;
	}

	public TreeVo() {
		super();
	}

}

数据访问层MenuDao

思路:

  1. Menu的格式是不满足easyui的tree组件的展示的数据格式的
  2. 实现,将将List《Menu》得到的单个Menu转成treevo,将treevo加入到nodes
package com.liyingdong.dao;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import com.liyingdong.entity.Menu;
import com.liyingdong.util.BaseDao;
import com.liyingdong.util.BuildTree;
import com.liyingdong.util.PageBean;
import com.liyingdong.vo.TreeVo;

public class MenuDao extends BaseDao<Menu>{
	public List<Menu> list(Menu menu,PageBean pageBean) throws InstantiationException, IllegalAccessException, SQLException{
		String sql="select * from t_easyui_menu ";
		return executeQuery(sql,Menu.class, pageBean);
	}
	
	public List<TreeVo<Menu>> menuNode(Menu menu,PageBean pageBean) throws InstantiationException, IllegalAccessException, SQLException{
		
		//1获取到数据库的数据
		List<Menu> list = this.list(menu, pageBean);
		//通过工具类完成指定格式的输出
        //2 定义容器
		List<TreeVo<Menu>> nodes=new ArrayList<TreeVo<Menu>>();
		//声明对象在循环外面节约jvm的资源
		TreeVo treevo=null;
		for (Menu p : list) {
			//实例化treevo对象
			treevo=new TreeVo<>();
			//设置id
			treevo.setId(p.getMenuid());
//			text相当于permission中的name
			treevo.setText(p.getMenuname());
//			设置父id
			treevo.setParentId(p.getParentid());
//			加入到集合
			nodes.add(treevo);
		}	
		//将集合转为条件符合的父子结构返回出去
		return  BuildTree.buildList(nodes,"-1");
	}
}

BuildTree类

这里buildList方法提供了父子分层的一个原理逻辑,带有两个参数,(需要关系分层的集合,指定id),灵活的实现了指定需要显示的父层。

实现原理:双重for循环,外层取父id,内层实现遍历id比对,符合条件则将当前对象加入到父id的子项中,时间复杂度呈线性关系,取决于集合的未知因素的多少来定,所以是O(n)的时间复杂度。

package com.liyingdong.util;


import com.liyingdong.vo.TreeVo;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class BuildTree {

	/**
	 * 默认-1为顶级节点
	 * @param nodes
	 * @param <T>
	 * @return
	 */
	public static <T> TreeVo<T> build(List<TreeVo<T>> nodes) {

		if (nodes == null) {
			return null;
		}
		//存放顶级节点(二级节点)容器
		List<TreeVo<T>> topNodes = new ArrayList<TreeVo<T>>();

		for (TreeVo<T> children : nodes) {
			String pid = children.getParentId();
			if (pid == null || "0".equals(pid)) {
				topNodes.add(children);
				//如果是顶级节点,那么结束当前循环,继续下一次的循环
				continue;
			}

			for (TreeVo<T> parent : nodes) {
				String id = parent.getId();
				if (id != null && id.equals(pid)) {
					parent.getChildren().add(children);
					children.setHasParent(true);
					parent.setChildren(true);
					continue;
				}
			}
		}
		//考虑到数据库表中没有顶级节点(一级节点)
		//
		TreeVo<T> root = new TreeVo<T>();
		if (topNodes.size() == 1) {
			//数据库有顶级节点这条数据
			root = topNodes.get(0);
		} else {
			//数据库中没有顶级节点,就进行创建一个
			root.setId("000");
			root.setParentId("-1");
			root.setHasParent(false);
			root.setChildren(true);
			root.setChecked(true);
			root.setChildren(topNodes);
			root.setText("顶级节点");
			Map<String, Object> state = new HashMap<>(16);
			state.put("opened", true);
			root.setState(state);
		}

		return root;
	}

	/**
	 * 指定idparam为顶级节点
	 * @param nodes
	 * @param idParam
	 * @param <T>
	 * @return
	 */
	
	public static <T> List<TreeVo<T>> buildList(List<TreeVo<T>> nodes, String idParam) {
//      判断非空
		if (nodes == null) {
			return null;
		}
		//存放顶级节点(二级节点)的容器
		List<TreeVo<T>> topNodes = new ArrayList<TreeVo<T>>();
//      外层循环
		for (TreeVo<T> children : nodes) {
//			获取到当前对象的父id
			String pid = children.getParentId();
//			判断id是否等于传进来的父id(根据数据库来判断)
			if (pid == null || idParam.equals(pid)) {
//				条件成立加入到当前二级节点下面
				topNodes.add(children);
//				跳过
				continue;
			}
//          内层循环
			for (TreeVo<T> parent : nodes) {
//				获取当前对象的id
				String id = parent.getId();
//				如果当前对象id等于父id就进来				
				if (id != null && id.equals(pid)) {
//					获取到二级节点的子节点容器加当前对象
					parent.getChildren().add(children);
//					有父节点
					children.setHasParent(true);
//					有子节点
					parent.setChildren(true);
//					跳过
					continue;
				}
			}
		}
//		返回存储好的树结构
		return topNodes;
	}

}

业务类MenuAction

这一步就是将获取到的数据进行响应并输出到浏览器中,它不用进行结果码的跳转因为它里面有一个转发输出的操作。

package com.liyingdong.web;
import java.sql.SQLException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.liyingdong.dao.MenuDao;
import com.liyingdong.entity.Menu;
import com.liyingdong.framework.ActionSupport;
import com.liyingdong.framework.ModelDriver;
import com.liyingdong.util.ResponseUtil;
public class MenuAction extends ActionSupport implements  ModelDriver<Menu>{
	private Menu menu=new Menu();
	private MenuDao menuDao=new MenuDao();
	@Override
	public Menu getModel() {
		// TODO Auto-generated method stub
		return menu;
	}
	
	public String menuNodes(HttpServletRequest req,HttpServletResponse resp) {
		try {
			//方法内部直接进行了输出到浏览器上
			ResponseUtil.writeJSON(resp, menuDao.menuNode(null, null));
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
}

ResponseUtil类
主要功能是进行响应,把传过来的对象转换为json格式的字符串,并且输出到浏览器上。

package com.liyingdong.util;

import java.io.PrintWriter;

import javax.servlet.http.HttpServletResponse;

import com.fasterxml.jackson.databind.ObjectMapper;

public class ResponseUtil {

	public static void write(HttpServletResponse response,Object o)throws Exception{
		response.setContentType("text/html;charset=utf-8");
		PrintWriter out=response.getWriter();
		out.println(o.toString());
		out.flush();
		out.close();
	}
	
	public static void writeJSON(HttpServletResponse response,Object o)throws Exception{
//		进行响应的字符编码
		response.setContentType("text/html;charset=utf-8");
//		ObjectMapper可以方便的将模型对象转换为JSON,或者JSON生成相应的模型类
		ObjectMapper om=new ObjectMapper();
//		writeValuesAsString的方法就可以把对像转化成json字符串
		String jsonstr= om.writeValueAsString(o);
//		获取到写流
		PrintWriter out=response.getWriter();
//		输出到浏览器。
		out.println(jsonstr.toString());
//		刷新
		out.flush();
		out.close();
//		关闭流
	}
}

实现效果

在这里插入图片描述
今天就分享到这了,有不懂之处欢迎评论区留言,拜拜。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值