LayUI之动态树

目录

一、介绍

1.1 动态树是什么

1.2 作用

二、思路流程

2.1 了解layui

2.2 思路流程

2.3 注意事项

三、订单菜单实例

动态树代码了解 

3.1 数据表

3.1.1 创建数据表

3.1.2 加入数据

3.2 架构jar包(自定义)

3.3 配置文件

3.4 实体类

3.5 实体dao类

3.6 模型控制器

3.7 前端页面(jsp)

学习后有什么收获


&=Stable Diffusion 美图活动一期=&

InsCode是一个集成了在线IDE、在线AI编程、在线算力租赁、在线项目部署以及在线SD 模型使用的综合代码开发平台。不论你是初级软件工程师,还是AI大模型爱好者,InsCode都能帮助你快速编写代码,运行项目。甚至在这里你还可以一键购买算力,训练大模型,开发自己的AI应用程序。


一、介绍

1.1 动态树是什么

LayUI的动态树(Dynamic Tree)是LayUI框架中提供的一种功能强大且易于使用的组件,用于在网页中展示具有层级结构的数据,LayUI是一款基于jQuery的前端开发框架,动态树是LayUI框架中提供的一个组件,用于在网页中展示具有层级结构的数据,如树形菜单。动态树组件可以实现数据的展开和折叠、节点的选中和取消选中等功能,并提供了丰富的事件和方法,方便开发者对树节点进行操作和控制。通过动态树组件,开发者可以方便地实现树状结构的数据展示和交互操作,提升用户体验。通常用于创建树形菜单或文件目录等场景。

动态树组件提供了丰富的功能和选项,使开发者能够方便地创建和交互树状结构的数据。下面是动态树组件的一些主要特点和功能:

  • --1. 数据格式灵活:动态树组件支持各种数据格式,如数组、JSON对象等。开发者可以根据需求选择最适合的数据格式来创建树形结构。

  • --2.数据异步加载:动态树可以通过异步加载方式获取数据,特别适用于大型数据量或需要从后端动态获取数据的情况。可以通过设置异步数据源来实现数据的动态加载。

  • --3.节点操作:动态树组件提供了一系列方法和事件,用于操作树节点。可以添加、删除、修改节点,展开、折叠节点,选择、取消选择节点等。

  • --4.样式自定义:可以通过设置节点的图标、颜色等样式,自定义节点的外观。同时也支持自定义节点的模板,使开发者可以灵活地展示节点的内容。

  • --5.事件监听:动态树组件提供了多个事件,可以监听节点的点击、展开、折叠等操作,以及其他自定义事件。通过事件监听,可以实现与节点交互的逻辑。

  • --6.扩展性:动态树组件支持扩展,可以根据实际需求扩展自定义功能,比如添加拖拽、搜索、排序等功能。

总的来说,LayUI的动态树组件为开发者提供了方便易用的工具,用于创建和操作树形结构的数据。它的灵活性和丰富的功能使开发者能够轻松地构建交互性强、用户友好的树状菜单或目录结构。

1.2 作用

LayUI的动态树组件在前端开发中具有很多作用和用途,下面详细说明几个主要的作用:

  • -- 1. 创建树形菜单:动态树组件可用于创建具有层级结构的树形菜单。树形菜单在很多网站和应用中常见,它可以有效组织和展示大量的菜单选项。通过动态树组件,可以轻松地创建多级菜单,并提供展开、折叠、选中等交互操作,方便用户浏览和选择菜单项。
  • -- 2. 构建文件目录:动态树可以用于构建文件目录结构。在一些文件管理系统、文档管理系统或网盘应用中,通常需要以树形结构展示文件夹和文件的层级关系。动态树组件可以帮助开发者实现文件目录的显示和操作,支持文件夹的展开、文件的选中等功能。
  • -- 3. 实现层级数据展示:有时候需要展示具有层级关系的数据,例如组织架构图、分类目录等。动态树组件可以将数据以树状结构的形式展示出来,使用户可以清晰地看到数据之间的层级关系,提供更好的信息展示效果。
  • -- 4. 动态加载大数据量:在一些数据量较大的场景下,使用动态加载的方式可以提升页面性能和用户体验。动态树组件支持异步数据加载,可以根据需要在用户交互时动态获取数据,避免一次性加载大量数据造成页面卡顿或加载时间过长的问题。
  • -- 5. 交互操作和数据筛选:动态树组件提供了丰富的节点操作方法和事件,可以实现节点的展开、折叠、选中等交互操作。同时,可以根据节点的属性或其他条件对树节点进行筛选,以显示符合条件的节点,方便用户快速定位和操作。

总的来说,LayUI的动态树组件在前端开发中广泛应用,可以用于创建各种具有层级结构的数据展示和交互场景。它提供了丰富的功能和选项,可以满足不同需求,并方便开发者进行定制和扩展。通过使用动态树组件,可以构建出用户友好、交互性强的树形结构,提升用户体验和数据展示效果。

二、思路流程

2.1 了解layui

LayUI是一个轻量级、简洁易用的前端UI框架,在快速开发和美化界面方面具有以下特性:

  • -- 1. 简单易用:LayUI具有简单、直观的API设计,易于上手和使用。它提供了丰富的UI组件和工具,使开发者能够快速构建页面和实现各种功能。
  • -- 2. 响应式布局:LayUI支持响应式布局,可适应不同屏幕尺寸的设备,如手机、平板和桌面电脑。它提供了一套灵活的栅格系统和类似于Bootstrap的响应式工具,使开发者可以轻松实现适配不同终端的布局。
  • -- 3. 模块化开发:LayUI采用了模块化开发的思想,将功能划分为独立的模块,开发者可以按需引入并组合使用。这种模块化的设计使得代码可维护性更高,并且可以避免冗余和重复的代码。
  • -- 4. 美观简洁:LayUI采用了简洁、现代的设计风格,UI元素精美而简洁。它提供了许多常用的UI组件和样式,如按钮、表单、导航菜单等,可以轻松创建美观的用户界面。
  • -- 5. 强大的组件:LayUI提供了丰富强大的UI组件,如弹窗、表格、分页、图表等,可以满足常见的页面需求。这些组件具有丰富的功能和样式定制选项,可以灵活满足不同的需求。
  • -- 6. 插件扩展:LayUI支持插件的扩展,开发者可以根据需求添加自定义的功能和样式。同时LayUI社区也提供了许多第三方插件和模块,方便开发者进行功能扩展。
  • -- 7. 文档和支持:LayUI官方提供了详细的文档和示例,使用者可以轻松查阅和学习。LayUI还有活跃的社区和技术支持,开发者可以在社区中提问和交流,获得帮助和解决问题。

总之,LayUI具有简单易用、响应式布局、模块化开发、美观简洁、强大的组件和插件扩展等特性。这些特性使得LayUI成为一个流行的前端框架,帮助开发者快速构建美观且功能丰富的界面。

2.2 思路流程

使用LayUI动态树的思路流程如下:

  1. 引入LayUI和动态树组件:在HTML页面中引入LayUI框架及相关的样式和脚本文件,确保能够正常加载所需资源。

  2. 准备数据源:准备树形结构的数据源,可以是数组或JSON对象。每个节点需要包含标识字段(如id和parentId),用于表示节点的层级关系。

  3. 初始化动态树:通过调用LayUI的动态树组件,创建一个动态树实例,并传入容器的选择器(指定容器元素的标识)作为参数。

  4. 配置动态树参数:通过配置参数来定义动态树的行为和外观。可以设置数据源字段的映射关系、图标、样式等。还可以设置异步加载、是否可多选、是否显示复选框等。

  5. 加载数据源并渲染树:将准备好的数据源传入动态树组件,并调用渲染方法,动态树将根据配置和数据源进行展示。

  6. 监听事件并处理交互:根据需要,通过绑定动态树组件的事件来监听用户的交互操作。例如,点击节点、展开节点、选择节点等事件。在事件的回调函数中,可以编写相应的操作逻辑。

  7. 优化和扩展功能:可以根据实际需求对动态树进行优化和扩展,例如添加拖拽排序、搜索过滤等功能,以提升用户体验。

2.3 注意事项

在使用LayUI动态树的过程中,还需要注意以下几点:

  • - - 数据源的格式:确保数据源的格式正确,并且每个节点有合适的标识字段来表示层级关系。这样才能保证动态树组件正常展示和交互。

  • - - 配置参数的准确性:仔细检查配置参数,确保参数名称和取值正确。参数配置不正确可能导致动态树组件无法正常工作。

  • - - 数据加载的性能:如果数据量较大,可以考虑使用异步加载的方式,通过事件监听和回调函数来动态获取数据,提高页面加载和渲染性能。

  • - - 事件处理的逻辑:根据需求合理处理事件回调函数中的逻辑,确保交互操作的准确性和用户体验。

  • - - 兼容性和版本:LayUI框架和动态树组件在不同版本中可能存在差异,注意选择合适的版本,并确保它们与其他组件和插件的兼容性。

三、订单菜单实例

动态树代码了解 

在进行实例操作之前可以先简单的熟悉LayUI动态树(基础菜单)的jsp页面的代码

导入LayUI的资源到项目中,在以下网站可以进行下载,或者在本人的博客LayUI的使用中进行下载资源包后进行导入你自己的项目

其中官方网站已经下线,可以访问该网站地址进行使用: 在线示例 - Layui

定义公共资源引入页面:header.jsp 代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html >
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<!-- 引入 layui.css -->
<link rel="stylesheet" href="${pageContext.request.contextPath }/static/js/layui/css/layui.css">
 
<!-- 引入 layui.js -->
<script src="${pageContext.request.contextPath }/static/js/layui/layui.js"></script>
<link rel="stylesheet" rev="stylesheet" href="${pageContext.request.contextPath }/static/css/iconfont.css"
	type="text/css" media="all">
<link rel="stylesheet" rev="stylesheet" href="${pageContext.request.contextPath }/static/css/login.css"
	type="text/css" media="all">

<body>

</body>
</html>

LayUI动态树(基础菜单)的jsp页面进行复制到自己页面中看看效果  代码如下:

注意:其中 <%@include file="common/header.jsp" %>的引入路径每个人的项目是不相同的,请合理的进行修改路径问题 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
 <%@include file="common/header.jsp" %>
<!DOCTYPE html >
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
 
</head>
<body>
<div class="layui-layout layui-layout-admin">
  <div class="layui-header">
    <div class="layui-logo layui-hide-xs layui-bg-black">layout demo</div>
    <!-- 头部区域(可配合layui 已有的水平导航) -->
    <ul class="layui-nav layui-layout-left">
      <!-- 移动端显示 -->
      <li class="layui-nav-item layui-show-xs-inline-block layui-hide-sm" lay-header-event="menuLeft">
        <i class="layui-icon layui-icon-spread-left"></i>
      </li>
      <!-- Top导航栏 -->
      <li class="layui-nav-item layui-hide-xs"><a href="">nav 1</a></li>
      <li class="layui-nav-item layui-hide-xs"><a href="">nav 2</a></li>
      <li class="layui-nav-item layui-hide-xs"><a href="">nav 3</a></li>
      <li class="layui-nav-item">
        <a href="javascript:;">nav groups</a>
        <dl class="layui-nav-child">
          <dd><a href="">menu 11</a></dd>
          <dd><a href="">menu 22</a></dd>
          <dd><a href="">menu 33</a></dd>
        </dl>
      </li>
    </ul>
    <!-- 个人头像及账号操作 -->
    <ul class="layui-nav layui-layout-right">
      <li class="layui-nav-item layui-hide layui-show-md-inline-block">
        <a href="javascript:;">
          <img src="//tva1.sinaimg.cn/crop.0.0.118.118.180/5db11ff4gw1e77d3nqrv8j203b03cweg.jpg" class="layui-nav-img">
          tester
        </a>
        <dl class="layui-nav-child">
          <dd><a href="">Your Profile</a></dd>
          <dd><a href="">Settings</a></dd>
          <dd><a href="login.jsp">Sign out</a></dd>
        </dl>
      </li>
      <li class="layui-nav-item" lay-header-event="menuRight" lay-unselect>
        <a href="javascript:;">
          <i class="layui-icon layui-icon-more-vertical"></i>
        </a>
      </li>
    </ul>
  </div>
  
  <div class="layui-side layui-bg-black">
    <div class="layui-side-scroll">
      <!-- 左侧导航区域(可配合layui已有的垂直导航) -->
      <ul id="menu" class="layui-nav layui-nav-tree" lay-filter="menu">
       <li class="layui-nav-item layui-nav-itemed">
          <a class="" href="javascript:;">menu group 1</a>
          <dl class="layui-nav-child">
            <dd><a href="javascript:;">menu 1</a></dd>
            <dd><a href="javascript:;">menu 2</a></dd>
            <dd><a href="javascript:;">menu 3</a></dd>
            <dd><a href="">the links</a></dd>
          </dl>
        </li>
        <li class="layui-nav-item">
          <a href="javascript:;">menu group 2</a>
          <dl class="layui-nav-child">
            <dd><a href="javascript:;">list 1</a></dd>
            <dd><a href="javascript:;">list 2</a></dd>
            <dd><a href="">超链接</a></dd>
          </dl>
        </li>
        <li class="layui-nav-item"><a href="javascript:;">click menu item</a></li>
        <li class="layui-nav-item"><a href="">the links</a></li> 
      </ul>
    </div>
  </div>
  
  <div class="layui-body">
    <!-- 内容主体区域 -->
    <div style="padding: 15px;">内容主体区域。记得修改 layui.css 和 js 的路径</div>
  </div>
  
  <div class="layui-footer">
    <!-- 底部固定区域 -->
            底部固定区域
  </div>
</div>
<script>
//JS 
layui.use(['element', 'layer', 'util'], function(){
  var element = layui.element
  ,layer = layui.layer
  ,util = layui.util
  ,$ = layui.$;
  
  //头部事件
  util.event('lay-header-event', {
    //左侧菜单事件
    menuLeft: function(othis){
      layer.msg('展开左侧菜单的操作', {icon: 0});
    }
    ,menuRight: function(){
      layer.open({
        type: 1
        ,content: '<div style="padding: 15px;">处理右侧面板的操作</div>'
        ,area: ['260px', '100%']
        ,offset: 'rt' //右上角
        ,anim: 5
        ,shadeClose: true
      });
    }
  });
  
});
</script>
</body>

</html>

基础的 LayUI菜单页面显示如图

利用架构进行页面订单的菜单实例

3.1 数据表

3.1.1 创建数据表

根据以上名称和属性类型进行创建表名为( t_easyui_permission )。 

3.1.2 加入数据

​ 

    1    书籍管理    书籍管理        0    1    0
2    新增(crud)    书籍新增    /bg/addBook.jsp    1    1    0
3    未上架    未上架书籍    /bg/listBook1.jsp    1    1    0
4    已上架    已上架书籍    /bg/listBook2.jsp    1    1    0
5    已下架    已下架书籍    /bg/listBook3.jsp    1    1    0
6    订单管理    商家的订单管理模块        0    1    0
7    未发货    未发货订单    /bg/listOrder1.jsp    6    1    0
8    已发货    已发货订单    /bg/listOrder2.jsp    6    1    0
9    已签收    已签收订单    /bg/listOrder3.jsp    6    1    0
10    订单管理    会员的订单管理模块        0    1    0
11    未发货    未发货订单    /bg/listMyOrder1.jsp    10    1    0
12    已发货    已发货订单    /bg/listMyOrder2.jsp    10    1    0
13    已签收    已签收订单    /bg/listMyOrder3.jsp    10    1    0
14    订单项    订单明细    /bg/listOrderItem.jsp    6    1    0
15    权限管理    顶级权限节点        -1    1    0

可以根据以上数据进行增加,或者自行修改 

3.2 架构jar包(自定义)

该架包是自定义MVC框架的jar架包,在本篇博客的最上面可以下载jar的资源包,下载后

进行解压即可使用,要将该文件的使用架包导入项目的WEB-INF文件中的lib文件中

如图所示:

3.3 配置文件

在项目中创建一个Source Folder的文件,命名为conf在该文件中,创建模型配置文件mvc.xml

代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<config>
	<action path="/orders" type="com.CloudJun.web.OrdersAction">
	</action>
</config>

并且在项目的WEB-INF文件中,创建配置文件名为:web.xml

代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <display-name>T269_mvc_blog</display-name>
  <servlet>
  	<servlet-name>mvc</servlet-name>
  	<servlet-class>com.zking.framework.DispatchServlet</servlet-class>
  	<init-param>
  		<param-name>configurationLocation</param-name>
  		<param-value>/mvc.xml</param-value>
  	</init-param>
  </servlet>
  <servlet-mapping>
  	<servlet-name>mvc</servlet-name>
  	<url-pattern>*.action</url-pattern>
  </servlet-mapping>
</web-app>

其中com.zking.framework.DispatchServlet是自定义架构里面的导入 ,并且这里的配置文件名称

<param-value>/mvc.xml</param-value>必须要跟上面的模型配置文件mvc.xml名称一致。

3.4 实体类

Orders 实体类 模型

package com.CloudJun.entity;

/**
 * @author Cloud.Jun
 * @com.CloudJun.entity
 * @Orders(说明):Orders类(实体/模型)
 */
public class Orders {

	private long id;
	private String name;
	private String description;
	private String url;
	private long pid;
	private int ismenu;
	private long displayno;
	public long getId() {
		return id;
	}
	public void setId(long id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getDescription() {
		return description;
	}
	public void setDescription(String description) {
		this.description = description;
	}
	public String getUrl() {
		return url;
	}
	public void setUrl(String url) {
		this.url = url;
	}
	public long getPid() {
		return pid;
	}
	public void setPid(long pid) {
		this.pid = pid;
	}
	public int getIsmenu() {
		return ismenu;
	}
	public void setIsmenu(int ismenu) {
		this.ismenu = ismenu;
	}
	public long getDisplayno() {
		return displayno;
	}
	public void setDisplayno(long displayno) {
		this.displayno = displayno;
	}
	@Override
	public String toString() {
		return "Orders [id=" + id + ", name=" + name + ", description=" + description + ", url=" + url + ", pid=" + pid
				+ ", ismenu=" + ismenu + ", displayno=" + displayno + "]";
	}
	public Orders(long id, String name, String description, String url, long pid, int ismenu, long displayno) {
		super();
		this.id = id;
		this.name = name;
		this.description = description;
		this.url = url;
		this.pid = pid;
		this.ismenu = ismenu;
		this.displayno = displayno;
	}
	public Orders() {
		super();
	}

	
	
}

3.5 实体dao类

OrdersDao类

package com.CloudJun.dao;

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

import com.CloudJun.entity.Orders;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zking.util.BaseDao;
import com.zking.util.BuildTree;
import com.zking.util.PageBean;
import com.zking.util.TreeVo;

/**
 * @author Cloud.Jun
 * @com.CloudJun.dao
 * @OrdersDao(说明):订单菜单的方法类(Dao层)
 */
public class OrdersDao extends BaseDao<Orders>{

	/**
	 * @param order
	 * @param pageBean
	 * @return 获取t_easyui_permission数据表中所有数据
	 * @throws Exception
	 */
	public List<Orders> list(Orders order, PageBean pageBean) throws Exception {
		String sql="select * from t_easyui_permission";
		return super.executeQuery(sql, Orders.class, pageBean);
	}
	
	/**
	 * @param order
	 * @param pageBean
	 * @return 将查询后的平级数据转换为父子关系的数据
	 * @throws Exception
	 */
	public List<TreeVo<Orders>> menus(Orders order, PageBean pageBean)throws Exception {
		//创建一个容器保存数据转换后的父子关系的数据
		List<TreeVo<Orders>> trpe = new ArrayList<TreeVo<Orders>>();
		//获取所有平级数据
		List<Orders> list = this.list(order, pageBean);
		//循环
		for (Orders p : list) {
			TreeVo<Orders> tp = new TreeVo<Orders>();
			//long强转String类型
			tp.setId(p.getId()+"");
			tp.setText(p.getName());
			tp.setParentId(p.getPid()+"");
			trpe.add(tp);
		}
		//返回调用工具类的方法将容器里的数据转成有父子关系的数据
		return BuildTree.buildList(trpe,"0");
	}
	
	public static void main(String[] args) throws Exception {
		List<TreeVo<Orders>> list = new OrdersDao().menus(null, null);
		ObjectMapper om = new ObjectMapper();
		System.out.println(om.writeValueAsString(list));
	}
	
}

其中此类继承的BaseDao工具类代码如下:

package com.zking.util;

import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author Cloud.Jun
 * @com.zking.util
 * @BaseDao(说明):所有Dao层的父类 BookDao UserDao OrderDao ...
 */
public class BaseDao<T> {

	/**
	 * 适合多表联查的数据返回
	 * @param sql
	 * @param pageBean
	 * @return
	 * @throws SQLException
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 */
	public List<Map<String, Object>> executeQuery(String sql, PageBean pageBean)
			throws SQLException, InstantiationException, IllegalAccessException {

		List<Map<String, Object>> list = new ArrayList<>();
		Connection con = DBAccess.getConnection();
		PreparedStatement pst = null;
		ResultSet rs = null;

		/*
		 * 是否需要分页? 无需分页(项目中的下拉框,查询条件教员下拉框,无须分页) 必须分页(项目中列表类需求、订单列表、商品列表、学生列表...)
		 */
		if (pageBean != null && pageBean.isPagination()) {
			// 必须分页(列表需求)
			String countSQL = getCountSQL(sql);
			pst = con.prepareStatement(countSQL);
			rs = pst.executeQuery();
			if (rs.next()) {
				pageBean.setTotal(String.valueOf(rs.getObject(1)));
			}

			// 挪动到下面,是因为最后才处理返回的结果集
			// -- sql=SELECT * FROM t_mvc_book WHERE bname like '%圣墟%'
			// -- pageSql=sql limit (page-1)*rows,rows 对应某一页的数据
			// -- countSql=select count(1) from (sql) t 符合条件的总记录数
			String pageSQL = getPageSQL(sql, pageBean);// 符合条件的某一页数据
			pst = con.prepareStatement(pageSQL);
			rs = pst.executeQuery();
		} else {
			// 不分页(select需求)
			pst = con.prepareStatement(sql);// 符合条件的所有数据
			rs = pst.executeQuery();
		}

		// 获取源数据
		ResultSetMetaData md = rs.getMetaData();
		int count = md.getColumnCount();
		Map<String, Object> map = null;
		while (rs.next()) {
			map = new HashMap<>();
			for (int i = 1; i <= count; i++) {
//				map.put(md.getColumnName(i), rs.getObject(i));
				map.put(md.getColumnLabel(i), rs.getObject(i));
			}
			list.add(map);
		}
		return list;

	}

	/**
	 * 
	 * @param sql
	 * @param attrs
	 *            map中的key
	 * @param paMap
	 *            jsp向后台传递的参数集合
	 * @return
	 * @throws SQLException
	 * @throws NoSuchFieldException
	 * @throws SecurityException
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 */
	public int executeUpdate(String sql, String[] attrs, Map<String, String[]> paMap) throws SQLException,
			NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
		Connection con = DBAccess.getConnection();
		PreparedStatement pst = con.prepareStatement(sql);
		for (int i = 0; i < attrs.length; i++) {
			pst.setObject(i + 1, JsonUtils.getParamVal(paMap, attrs[i]));
		}
		return pst.executeUpdate();
	}

	/**
	 * 批处理
	 * @param sqlLst
	 * @return
	 */
	public static int executeUpdateBatch(String[] sqlLst) {
		Connection conn = null;
		PreparedStatement stmt = null;
		try {
			conn = DBAccess.getConnection();
			// 设置不自动提交
			conn.setAutoCommit(false);
			for (String sql : sqlLst) {
				stmt = conn.prepareStatement(sql);
				stmt.executeUpdate();
			}
			conn.commit();
		} catch (Exception e) {
			try {
				conn.rollback();
			} catch (SQLException e1) {
				e1.printStackTrace();
				throw new RuntimeException(e1);
			}
			e.printStackTrace();
			throw new RuntimeException(e);
		} finally {
			DBAccess.close(conn, stmt, null);
		}
		return sqlLst.length;
	}

	/**
	 * 通用的增删改方法
	 * 
	 * @param book
	 * @throws Exception
	 */
	public int executeUpdate(String sql, T t, String[] attrs) throws Exception {
		// String[] attrs = new String[] {"bid", "bname", "price"};
		Connection con = DBAccess.getConnection();
		PreparedStatement pst = con.prepareStatement(sql);
		// pst.setObject(1, book.getBid());
		// pst.setObject(2, book.getBname());
		// pst.setObject(3, book.getPrice());
		/*
		 * 思路: 1.从传进来的t中读取属性值 2.往预定义对象中设置了值
		 * 
		 * t->book f->bid
		 */
		for (int i = 0; i < attrs.length; i++) {
			Field f = t.getClass().getDeclaredField(attrs[i]);
			f.setAccessible(true);
			pst.setObject(i + 1, f.get(t));
		}
		return pst.executeUpdate();
	}

	/**
	 * 通用分页查询
	 * 
	 * @param sql
	 * @param clz
	 * @return
	 * @throws Exception
	 */
	public List<T> executeQuery(String sql, Class<T> clz, PageBean pageBean) throws Exception {
		List<T> list = new ArrayList<T>();
		Connection con = DBAccess.getConnection();
		;
		PreparedStatement pst = null;
		ResultSet rs = null;

		/*
		 * 是否需要分页? 无需分页(项目中的下拉框,查询条件教员下拉框,无须分页) 必须分页(项目中列表类需求、订单列表、商品列表、学生列表...)
		 */
		if (pageBean != null && pageBean.isPagination()) {
			// 必须分页(列表需求)
			String countSQL = getCountSQL(sql);
			pst = con.prepareStatement(countSQL);
			rs = pst.executeQuery();
			if (rs.next()) {
				pageBean.setTotal(String.valueOf(rs.getObject(1)));
			}

			// 挪动到下面,是因为最后才处理返回的结果集
			// -- sql=SELECT * FROM t_mvc_book WHERE bname like '%圣墟%'
			// -- pageSql=sql limit (page-1)*rows,rows 对应某一页的数据
			// -- countSql=select count(1) from (sql) t 符合条件的总记录数
			String pageSQL = getPageSQL(sql, pageBean);// 符合条件的某一页数据
			pst = con.prepareStatement(pageSQL);
			rs = pst.executeQuery();
		} else {
			// 不分页(select需求)
			pst = con.prepareStatement(sql);// 符合条件的所有数据
			rs = pst.executeQuery();
		}

		while (rs.next()) {
			T t = clz.newInstance();
			Field[] fields = clz.getDeclaredFields();
			for (Field f : fields) {
				f.setAccessible(true);
				f.set(t, rs.getObject(f.getName()));
			}
			list.add(t);
		}
		return list;
	}

	/**
	 * 将原生SQL转换成符合条件的总记录数countSQL
	 * 
	 * @param sql
	 * @return
	 */
	private String getCountSQL(String sql) {
		// -- countSql=select count(1) from (sql) t 符合条件的总记录数
		return "select count(1) from (" + sql + ") t";
	}

	/**
	 * 将原生SQL转换成pageSQL
	 * 
	 * @param sql
	 * @param pageBean
	 * @return
	 */
	private String getPageSQL(String sql, PageBean pageBean) {
		// (this.page - 1) * this.rows
		// pageSql=sql limit (page-1)*rows,rows
		return sql + " limit " + pageBean.getStartIndex() + "," + pageBean.getRows();
	}
}

其中有使用到BuildTree 工具类,作用是将平级关系转换为有父子关系的数据

代码如下:

package com.zking.util;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
 * @author Cloud.Jun
 * @BuildTree(说明):
 */
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 || "-1".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) {

			String pid = children.getParentId();
			if (pid == null || idParam.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;
				}
			}

		}
		return topNodes;
	}

}

3.6 模型控制器

OrdersAction 控制器

package com.CloudJun.web;

import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.CloudJun.dao.OrdersDao;
import com.CloudJun.entity.Orders;
import com.zking.framework.ActionSupport;
import com.zking.framework.ModelDriver;
import com.zking.util.ResponseUtil;
import com.zking.util.TreeVo;

/**
 * @author Cloud.Jun
 * @com.CloudJun.web
 * @OrdersAction(说明):
 * 1.获取url请求地址进行处理
 * 2.获取数据并且进行转化后将数据传递到页面
 */
public class OrdersAction extends ActionSupport implements ModelDriver<Orders>{

	//实例化orders实体(模型)
	private Orders orders= new Orders();
	//实例化OrdersDao实体的方法类(Dao层)
	private OrdersDao ordersDao= new OrdersDao();
	
	public void menus(HttpServletRequest req, HttpServletResponse resp) {
		try {
			//调用方法获取有父子级关系的数据
			List<TreeVo<Orders>> menus = ordersDao.menus(null, null);
			//调用工具类将该数据(menus)传递到前端
			ResponseUtil.writeJson(resp, menus);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	@Override
	public Orders getModel() {
		return orders;
	}

}

其中继承的 ActionSupport类(所有模型控制器的总控制器,相当于父类的意思)和实现ModelDriver

接口(模型驱动接口)该两个都是自定义框架里面已经编写好了的架包及功能。

其中有一个工具类为ResponseUtil 类 代码如下:

package com.zking.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{
		ObjectMapper om = new ObjectMapper();
//		om.writeValueAsString(o)代表了json串
		write(response, om.writeValueAsString(o));
	}
}

3.7 前端页面(jsp)

使用LayUI动态树的修改/优化后的jsp页面代码:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE>
<html>
<head>
  <%@include file="common/header.jsp" %>
  <!-- <script type="text/javascript" src="js/index.js"></script> -->
</head>
<body>
<div class="layui-layout layui-layout-admin">
  <div class="layui-header">
    <div class="layui-logo layui-hide-xs layui-bg-black">layout demo</div>
    <!-- 头部区域(可配合layui 已有的水平导航) -->
    <ul class="layui-nav layui-layout-left">
      <!-- 移动端显示 -->
      <li class="layui-nav-item layui-show-xs-inline-block layui-hide-sm" lay-header-event="menuLeft">
        <i class="layui-icon layui-icon-spread-left"></i>
      </li>
      <!-- Top导航栏 -->
      <li class="layui-nav-item layui-hide-xs"><a href="">nav 1</a></li>
      <li class="layui-nav-item layui-hide-xs"><a href="">nav 2</a></li>
      <li class="layui-nav-item layui-hide-xs"><a href="">nav 3</a></li>
      <li class="layui-nav-item">
        <a href="javascript:;">nav groups</a>
        <dl class="layui-nav-child">
          <dd><a href="">menu 11</a></dd>
          <dd><a href="">menu 22</a></dd>
          <dd><a href="">menu 33</a></dd>
        </dl>
      </li>
    </ul>
    <!-- 个人头像及账号操作 -->
    <ul class="layui-nav layui-layout-right">
      <li class="layui-nav-item layui-hide layui-show-md-inline-block">
        <a href="javascript:;">
          <img src="//tva1.sinaimg.cn/crop.0.0.118.118.180/5db11ff4gw1e77d3nqrv8j203b03cweg.jpg" class="layui-nav-img">
          tester
        </a>
        <dl class="layui-nav-child">
          <dd><a href="">Your Profile</a></dd>
          <dd><a href="">Settings</a></dd>
          <dd><a href="login.jsp">Sign out</a></dd>
        </dl>
      </li>
      <li class="layui-nav-item" lay-header-event="menuRight" lay-unselect>
        <a href="javascript:;">
          <i class="layui-icon layui-icon-more-vertical"></i>
        </a>
      </li>
    </ul>
  </div>
  
  <div class="layui-side layui-bg-black">
    <div class="layui-side-scroll">
      <!-- 左侧导航区域(可配合layui已有的垂直导航) -->
      <ul id="menu" class="layui-nav layui-nav-tree" lay-filter="menu">
      <li class="layui-nav-item layui-nav-itemed">
          <a class="" href="javascript:;">menu group 1</a>
          <dl class="layui-nav-child">
            <dd><a href="javascript:;">menu 1</a></dd>
            <dd><a href="javascript:;">menu 2</a></dd>
            <dd><a href="javascript:;">menu 3</a></dd>
            <dd><a href="">the links</a></dd>
          </dl>
        </li>
        <li class="layui-nav-item">
          <a href="javascript:;">menu group 2</a>
          <dl class="layui-nav-child">
            <dd><a href="javascript:;">list 1</a></dd>
            <dd><a href="javascript:;">list 2</a></dd>
            <dd><a href="">超链接</a></dd>
          </dl>
        </li>
        <li class="layui-nav-item"><a href="javascript:;">click menu item</a></li>
        <li class="layui-nav-item"><a href="">the links</a></li> 
      </ul>
    </div>
  </div>
  
  <div class="layui-body">
    <!-- 内容主体区域 -->
    <div style="padding: 15px;">内容主体区域。记得修改 layui.css 和 js 的路径</div>
  </div>
  
  <div class="layui-footer">
    <!-- 底部固定区域 -->
            底部固定区域
  </div>
</div>
<script>
layui.use(['element', 'layer', 'util'], function(){
  var element = layui.element
  ,layer = layui.layer
  ,util = layui.util
  ,$ = layui.$;
  
  $.ajax({
	  url:"${pageContext.request.contextPath }/orders.action?methodName=menus",
	  dataType:'json',
      success:function(data){
			/* console.log(data); */
			/* 定义标签要拼接的文本内容  */
			let datacontent = '';
			$.each(data,function(i,n){
				datacontent += ' <li class="layui-nav-item layui-nav-itemed">';
				datacontent +='<a class="" href="javascript:;">'+n.text+'</a>';
				
				/* 判断是否有子节点有就进行子菜单增加,没有就不加 */
				if(n.hasChildren){
					datacontent +='<dl class="layui-nav-child">';
					/* 循环所有的子节点  n.children*/
					$.each(n.children,function(index,node){
						datacontent += '<dd><a href="javascript:;">'+node.text+'</a></dd>';
					})
					datacontent += ' </dl> ';
				}
				datacontent += ' </li> ';
			})
			/* 重置里面的文本内容 */
			$("#menu").html(datacontent);
			element.render('menu');
		}
  });
 
    
  });
</script>
</body>
</html>

使用LayUI动态树的修改/优化后的jsp页面,显示效果如图:

 由以上显示可以看出,在每个项目中所有的数据都应该是活的数据,而不是只是默认编写在jsp

页面是的基础数据,而基础数据对项目而言是没有用的,所有LayUI动态树及自定义MVC架构后

就可以使数据库的数据进行优化后(将平级数据转换为父子关系的数据)显示在前端页面中。

学习后有什么收获

学习LayUI动态树可以给我们带来以下几个方面的收获:

  • - - 1. 提高前端开发效率:LayUI动态树作为一个成熟的前端组件,提供了一套简洁、易用的API和丰富的功能选项。学习并掌握LayUI动态树的使用,可以大大缩短开发时间,提高前端开发效率。
  • - - 2. 优化用户界面:动态树可以将数据以树形结构的形式展示出来,有助于优化用户界面的展示效果。通过合理设计和使用动态树,可以更好地组织和展示复杂的数据集合,提升用户的视觉体验和操作便利性。
  • - - 3. 实现复杂数据交互:动态树组件不仅可以展示静态数据,还支持异步加载和动态操作。学习动态树的使用,可以帮助我们处理复杂的数据交互场景,如动态加载、筛选、展开、折叠等操作,提升用户的交互体验。
  • - - 4. 增强前端技术能力:通过学习LayUI动态树,可以增强对前端技术的理解和掌握。了解底层的实现原理、UI组件的设计思路,以及常见的前端开发模式,有助于我们提升前端技能水平,更好地应对各种项目需求。
  • - - 5. 扩展和应用到其他项目:学习LayUI动态树的使用,不仅限于当前项目,还可以将所学的知识和技术应用到其他项目中。动态树作为一个常见的前端组件,有广泛的应用场景,掌握了动态树的使用,可以为今后的项目开发提供更多可能性和选择。

总的来说,学习LayUI动态树可以帮助我们提高前端开发效率,优化用户界面,实现复杂数据交互,增强前端技术能力,以及扩展和应用到其他项目中。这些收获将为我们的工作和学习带来很大的价值和便利。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值