layui实现Tree组件前后端交互

前言

关于树组件的话,layui官方提供的文档资料不太全面,本篇将分享Tree组件与后台交互实现动态加载数据。

运行效果

老板登录后显示的权限
在这里插入图片描述
普通用户显示的权限
在这里插入图片描述

Tree组件

1.Tree组件的加载方式

官方文档的基础说明部分可以静下心去仔细看一看(很有必要),我这里采取的非模块加载方式,对应的script的文件引入是layui.all.js

注意:script要在写在body底部哦!,不然加载不出来数据。

因为:浏览器生成Dom树的时候是一行一行读HTML代码的,script标签放在最后面就不会影响前面的页面的渲染

这里我用的是ajax来请求后台数据的,而后在success函数中拿到返回的json进行tree控件数据的加载。

1.1选项卡

选项卡的话是配合于tree组件中的点击事件,其中两个核心方法。

  1. 打开选项卡的方法:element.tabAdd('tabs',{title:xx,conten:xx});
  2. 判断选项卡的id是否打开过,$("li[lay-id='" + node.data.id + "']").length;

在这里插入图片描述

<script src="${pageContext.request.contextPath }/static/js/layui/layui.all.js" charset="utf-8"></script>
<script>
;!function(){
	//加载所需要的模块
	 var $=layui.$;
	  var element = layui.element;
	  var table = layui.table;
	  var layer=layui.layer;
	  var form=layui.form;
	  var tree = layui.tree;
      var url=$("#ctx").val();
      layer.msg('酷毙了。。', {icon: 1});
      
      layer.msg(RoleId);
      //获取角色权限id
      var RoleId=   $("#RoleId").val();
    //请求tree控件的数据
       $.ajax({
		  type: "post",
          url: url+"/permission.action?methodName=menuTree",
          dataType: 'json',
          data:{rid:RoleId},//获取角色权限id去加载数据
          success: function (data) {
        	  tree.render({
  			    elem: '#test13'
  			    ,data: data//数据源
  			    ,isJump:true//否允许点击节点时弹出新窗口跳转
  			  ,spread:true//节点是否初始展开
  			    ,showLine: false  //是否开启连接线
  			  	,click: function (node) {//点击事件
                     var exist = $("li[lay-id='" + node.data.id + "']").length;//判断是不是用重复的选项卡
                    if (exist > 0) {
                        element.tabChange('tabs', node.data.id);// 切换到已有的选项卡
                    } else {
                        if (node.data.attributes.self.url != "") {// 判断是否需要新增选项卡
                           //新增选项卡
                        	element.tabAdd('tabs',
                                {
                                    title: node.data.title,//获取标题
                                    content: '<iframe scrolling="yes" frameborder="0" src="'+url+node.data.attributes.self.url+'"width="100%" height="100%"></iframe>'
                                    ,
                                    id: node.data.id
                                });
                              //跳转到指定的选项卡
                            element.tabChange('tabs', node.data.id);
                        }
                    }   
              }
  			  }); 
        	  debugger;
            }
	  }) 
}(); 

</script>

2.Tree组件的渲染格式

这里可以看到它所提供支持的格式必不可少的有titlechildren属性,如果后台传入的json中没对应上这两个属性的话是出不来想要的效果,而后就是需要绑定元素,和定义数据接口。
在这里插入图片描述

3.基础参数

这个是控件里面的基础参数,都比较常用。
在这里插入图片描述

4.数据源属性选项

总之定义的json格式属性一定要向下面表中属性对齐。
在这里插入图片描述

后台代码实现

1.定义对应数据格式实体

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 title;
	/**
	 * 节点状态,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 getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	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 title, 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.title = title;
		this.state = state;
		this.checked = checked;
		this.attributes = attributes;
		this.children = children;
		this.hasParent = isParent;
		this.hasChildren = isChildren;
		this.parentId = parentID;
	}

	public TreeVo() {
		super();
	}

	@Override
	public String toString() {
		return "TreeVo [id=" + id + ", title=" + title + ", state=" + state + ", checked=" + checked + ", attributes="
				+ attributes + ", children=" + children + ", parentId=" + parentId + ", hasParent=" + hasParent
				+ ", hasChildren=" + hasChildren + "]";
	}

}

2.数据转换

把查询到的数据转换为指定格式。

package com.liyingdong.dao;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.liyingdong.entity.Permission;
import com.liyingdong.util.BaseDao;
import com.liyingdong.util.BuildTree;
import com.liyingdong.util.PageBean;
import com.liyingdong.vo.TreeVo;

public class PermissionDao extends BaseDao<Permission> {

	/**
	 * 
	 * 是直接从数据库获取到的数据
	 * @param permission
	 * @param pageBean
	 * @return
	 * @throws Exception
	 */
	public List<Permission> list(Permission permission,String json) throws Exception {
		//获取需要包含的字符串
		String sql="select * from t_easyui_Permission where id in("+json+") ";

		return super.executeQuery(sql, Permission.class, null);
	}
	
	public List<TreeVo<Permission>> topNode(String rid,String json) throws Exception {
	    //查询权限对应的子项
		List<Permission> list = this.list(null, json);
	    //声明顶级容器
		List<TreeVo<Permission>> nodes = new ArrayList<TreeVo<Permission>>();
	
		TreeVo<Permission> treeVo = null;
		//遍历实现把数据库的结构转换为前端需要的
		for (Permission p : list) {
			treeVo = new TreeVo<>();
			treeVo.setId(p.getId()+"");//id
			treeVo.setTitle(p.getName());//标题
			treeVo.setParentId(p.getPid()+"");//父id
			Map<String, Object> attributes = new HashMap<String, Object>();
			attributes.put("self", p);//属性
			treeVo.setAttributes(attributes);
			nodes.add(treeVo);
		}
		//获取权限对应的数据
		return BuildTree.buildList(nodes,nodes.get(0).getParentId());
	
	}

}

3.树结构存储的处理

这个方法是把转换好的数据进行树结构处理,让它用有层次。

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;
	}

角色处理

1.思路

关于角色的权限问题是由中间表来进行判断的,账号表type–》权限表–》主表
我们可以根据登录者的账号来拿到用户的type,然后存入做用域进行跳转到主界面进行ajax请求带type过去type查询权限表拿到结果集进行pid的拼接+逗号的截取,拼接成需要的串后,在进行sql in(截取好的串)查询到数据进行转换返回到前端渲染。

在这里插入图片描述

2.PermissionAction

public String menuTree(HttpServletRequest req,HttpServletResponse resp) {
		try {
			RoleDao roleDao = new RoleDao();
			String rid = req.getParameter("rid");
			//获取到登录用户的权限id
			List<Role> list = roleDao.list(rid, null);
			StringBuffer  s=new StringBuffer();
			//截取需要串   
			for (Role rl : list) {
			     s.append(rl.getPid()+",");
			}
			//截取掉最后一个逗号
			int last = s.lastIndexOf(",");
		    String json = s.toString().substring(0, last);
		    //sql  in包含查询传入的字符串,转为需要的格式输出到浏览器中
			ResponseUtil.writeJson(resp, this.pd.topNode(rid, json));
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

3.UserDao

public class UserDao extends BaseDao<User>{
	
	public List<User>  list(User user) throws Exception {
		String	sql="select*from t_easyui_user  where name='"+user.getName()+"' ";
		return super.executeQuery(sql, User.class, null);
	}
	
}

4.RoleDao

public class RoleDao extends BaseDao<Role>{

public List<Role> list(String rid,PageBean pageBean) throws Exception {
		
		String sql1="select *from t_easyui_role_permission where rid="+rid;
		
		return super.executeQuery(sql1, Role.class, pageBean);
	}
	
}

5.UserAction

//登录
	public String login(HttpServletRequest req, HttpServletResponse resp) throws Exception {
		
		 User u = this.userDao.list(user).get(0);
		 
		 PrintWriter out = resp.getWriter();
		 if(u!=null) {
			 //存入作用域进行转发
			 req.setAttribute("name",u.getName());
			 req.setAttribute("pwd", u.getPwd());
			 req.setAttribute("type", u.getType());
			 out.print("<script>alert('登录成功!')</script>");
			 return "index";
		 }
		 out.print("<script>alert('账号或者密码错误!!')</script>");
		return "login";
	}

6.mvc.xml

<?xml version="1.0" encoding="UTF-8"?>
<config>
	<action path="/permission" type="com.liyingdong.web.PermissionAction">
	</action>
	<action path="/book" type="com.liyingdong.web.BookAction">
	</action>
	
	<action path="/UserAction" type="com.liyingdong.web.UserAction">
	<forward name="index" path="/index.jsp" redirect="false"></forward>
	</action>
	
</config>

7.login.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>用户登录</title>
		<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath }/css/bootstrap.min.css" />
		<style>
			.form-signin{
				width: 400px;
				/* 相对定位 :relative    绝对定位:absolute*/
				position: relative;
				top: 100px;
				left: 50%;
				margin-left: -200px;
			}
    </style>
	</head>
	<body>
		<form class="form-signin" action="${pageContext.request.contextPath }/UserAction.action?methodName=login" method="post">
			<div class="text-center mb-4">
				<img class="mb-4" src="/docs/assets/brand/bootstrap-solid.svg" alt="" width="72" height="72">
				<h1 class="h3 mb-3 font-weight-normal">用户登录</h1>
			</div>

			<div class="form-label-group">
				<input type="text" id="name" name="name" class="form-control" placeholder="请输入用户名" required autofocus>
			</div>

			<div class="form-label-group">
				<input type="password" id="pwd" name="pwd" class="form-control" placeholder="请输入密码" required>
			</div>

			<div class="checkbox mb-3">
				<label>
					<input type="checkbox" value="remember-me"> Remember me
				</label>
			</div>
			<button class="btn btn-lg btn-primary btn-block" type="submit">登录</button>
			<p class="mt-5 mb-3 text-muted text-center">&copy; 2017-2020</p>
		</form>
		<script src="js/bootstrap.min.js" type="text/javascript" charset="utf-8"></script>
	</body>
</html>

8.index.jsp

<%@ 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>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" href="${pageContext.request.contextPath }/static/js/layui/css/layui.css"  media="all">
<title>主界面</title>
</head>
<body class="layui-layout-body">

<input type="hidden" id="ctx" value="${pageContext.request.contextPath }" />
<div class="layui-layout layui-layout-admin">
  <div class="layui-header">
    <div class="layui-logo">东哥的后台</div>
    <!-- 头部区域 -->
    <ul class="layui-nav layui-layout-left">
      <li class="layui-nav-item">
        <a href="javascript:;">其它系统</a>
        <dl class="layui-nav-child">
          <dd><a href="">邮件管理</a></dd>
          <dd><a href="">消息管理</a></dd>
          <dd><a href="">授权管理</a></dd>
        </dl>
      </li>
    </ul>
    <ul class="layui-nav layui-layout-right">
      <li class="layui-nav-item">
        <a href="javascript:;">
          <img src="http://t.cn/RCzsdCq" class="layui-nav-img">
                                                       李瀛东
        </a>
        <dl class="layui-nav-child">
          <dd><a href="">基本资料</a></dd>
          <dd><a href="">安全设置</a></dd>
        </dl>
      </li>
      <li class="layui-nav-item"><a href="">退出</a></li>
    </ul>
  </div>
  
  <div class="layui-side layui-bg-black">
    <div class="layui-side-scroll">
      <!-- 左侧导航区域 -->
      <div id="test13" class="demo-tree-more"></div>
    </div>
  </div>
  <div class="layui-body">
    <!-- 内容主体区域 -->
             我是主体区域
    <div style="padding: 10px;">
    <div class="layui-inline">
    </div>
    
      <!-- 选项卡要显示的地方 -->
     <div class="layui-body">
        <div class="layui-tab" lay-filter="tabs" lay-allowClose="true">
            <ul class="layui-tab-title">
            </ul>
            <div class="layui-tab-content">
             数据表格
            </div>
        </div>
    </div> 
  </div> 
  
  
  <div class="layui-footer">
    <!-- 底部固定区域 -->
    © layui.com - 底部固定区域
  </div>
</div>

<!-- 登录时的账号权限 -->
<input type="hidden" id="RoleId" value="${type}"/>

<script src="${pageContext.request.contextPath }/static/js/layui/layui.all.js" charset="utf-8"></script>
<script>
;!function(){
	//加载所需要的模块
	 var $=layui.$;
	  var element = layui.element;
	  var table = layui.table;
	  var layer=layui.layer;
	  var form=layui.form;
	  var tree = layui.tree;
      var url=$("#ctx").val();
      layer.msg('酷毙了。。', {icon: 1});
      
      layer.msg(RoleId);
      //获取角色权限id
      var RoleId=   $("#RoleId").val();
    //请求tree控件的数据
       $.ajax({
		  type: "post",
          url: url+"/permission.action?methodName=menuTree",
          dataType: 'json',
          data:{rid:RoleId},//获取角色权限id去加载数据
          success: function (data) {
        	  tree.render({
  			    elem: '#test13'
  			    ,data: data//数据源
  			    ,isJump:true//否允许点击节点时弹出新窗口跳转
  			  ,spread:true//节点是否初始展开
  			    ,showLine: false  //是否开启连接线
  			  	,click: function (node) {//点击事件
                     var exist = $("li[lay-id='" + node.data.id + "']").length;//判断是不是用重复的选项卡
                    if (exist > 0) {
                        element.tabChange('tabs', node.data.id);// 切换到已有的选项卡
                    } else {
                        if (node.data.attributes.self.url != "") {// 判断是否需要新增选项卡
                           //新增选项卡
                        	element.tabAdd('tabs',
                                {
                                    title: node.data.title,//获取标题
                                    content: '<iframe scrolling="yes" frameborder="0" src="'+url+node.data.attributes.self.url+'"width="100%" height="100%"></iframe>'
                                    ,
                                    id: node.data.id
                                });
                              //跳转到指定的选项卡
                            element.tabChange('tabs', node.data.id);
                        }
                    }   
              }
  			  }); 
        	  debugger;
            }
	  }) 
}(); 

</script>
</body>
</html>
  • 5
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值