EasyUI&Layui树形菜单实现

目录

一、概念

二、为什么学习EasyUI

三、入门

前端实现

EasyUI

1、layout、Tree、tabs

2、文档说明

3、代码

layui

1、栅格,Tree,tabs

2、indexjsp代码

3、index.js

后端实现

项目结构

1、步骤分析

2、实现

总结:


一、概念

前端框架,帮助我们快速开发前端界面或者后端管理员界面!后端框架为我们解决了代码的复用性,当然前端也一

样,为我们提供了封装好的js,css,我们按照它的学习文档进行开发,少量代码就能完成不错的界面效果!

EasyUI=jQuery+HTML4

2016年发行的前端框架,文档齐全,免费!

bootstrap=jQuery+HTML5

2016-1028,收费,api文档不齐全。

layui

2018-2021,免费文档不齐全。

二、为什么学习EasyUI

从界面效果上来讲比bootstrap和layui都要差!

但是从学习文档的完整性,前端框架的稳定性,组件的丰富性考虑,EasyUI优于layui。本人第一

次接触使用的前端框架是layui,学习起来挺吃力。我觉得这个是要不断积累的过程,在已经有前端

框架的学习经验上去学习新的框架会比第一次接触轻松许多!一定要掌握好学习方法!EasyUI的

文档很齐全,非常适合入门学习。当然选择什么框架进行开发,从公司的角度出发:成本、公司的

后端技术人员前端功底、前端的社区活跃度。

三、入门

首先看说明文档:

EasyUI&Layui树形菜单实现_第1张图片

说明了在使用它的组件时,属性、事件、方法定义在那里。这是EasyUI的一个使用规范。不同的

框架会有不同的使用规范。

 EasyUI&Layui树形菜单实现_第2张图片

我们需要使用EasyUI,就必须导入它的css,js文件。

这里需要注意一点,EasyUI.js是基于jQuery之上的。js是一门语言,而jQuery是js的框架,

jQuery对js进行封装,EasyUI.js则是使用jQuery编写出来的。所以EasyUI.js是依赖与jQuery

的。

前端实现

EasyUI

1、layout、Tree、tabs

EasyUI&Layui树形菜单实现_第3张图片

这里使用到了组件:layouttreetabs

2、文档说明

EasyUI&Layui树形菜单实现_第4张图片

 EasyUI&Layui树形菜单实现_第5张图片

 EasyUI&Layui树形菜单实现_第6张图片

 还有更多的使用方式,这里仅仅截取部分,全内容看文档!

3、代码

index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>




EasyUI 后台管理界面
   
   
   
 
  


	

     inde.js文件

    $(function(){
    	$('#stu_tree').tree({    
    	    url:'menu.action?methodName=list',//树形菜单数据接口
    	    onClick: function(node){//树形菜单的点击事件 node为被点击的节点对象
                //判断标题为node.text的tab是否存在
    			var exists = $("#stu_tab").tabs("exists", node.text);
    			if(exists){//存在
    				$("#stu_tab").tabs("select", node.text);//选择
    			}else{//不存在
    				$('#stu_tab').tabs('add',{//打开新的tab页
    				    title: node.text , // 新的tab页的标题为被点击的菜单名 
    				    content:'',//内容为对应的界面
    				    closable:true,    
    				    tools:[{ //工具   
    				        iconCls:'icon-mini-refresh', //图标
    				        handler:function(){    //图标点击事件
    				            alert('refresh');    
    				        }    
    				    }]    
    				});  
    			}
    		}
    	});  
    })

    数据接口是来自数据库中,可以先使用demo中的tree_data1.json 文件。这里接收的数据是

    json格式哦。

    从上述案例可以看到属性,事件和方法是怎么定义的了。

    这里可以先给大家看一下tree的数据接口格式

    EasyUI&Layui树形菜单实现_第7张图片

    通过这个结构是否能想到我们用来接收数据的结构?  

    layui

    1、栅格,Tree,tabs

    效果图:

    EasyUI&Layui树形菜单实现_第8张图片

    没有花时间去写css样式了,简单的效果展示!  

    2、index.jsp代码

    <%@ page language="java" contentType="text/html; charset=UTF-8"
    	pageEncoding="UTF-8"%>
    <%@ include file="common.jsp"%>
    
    
    
    
    Insert title here
    
    
    
    	
     

      可能会疑问了,为什么没有看到导入layui.js的这些语句?

      几乎每个页面都有用到这些公共资源,将其转入到一个公共资源jsp界面,然后其他界面需要

      的话就包含其界面即可。界面会简洁许多

      common.jsp

      <%@ page language="java" contentType="text/html; charset=UTF-8"
      	pageEncoding="UTF-8"%>
      
      
      
      
      Insert title here
      
      
      
      
      
      
      

      3、index.js

      $(function() {
      	layui.use([ 'tree', 'element', 'jquery' ], function() {
      		var element = layui.element;
      		var tree = layui.tree;
      		var $ = layui.jquery;
      		$.ajax({
      			type : 'post',
      			url : "menu.action?methodName=list",
      			dataType : "json",
      			success : function(data) {
      				tree.render({
      					elem : '#menuTree',
      					data : data,
      					click : function(node) {
      						//判断是否有打开过该节点对应的tab页
      						var exist = $("li[lay-id='" + node.data.id + "']").length;
      						if (exist > 0) {
      							element.tabChange('menuTab', node.data.id);// 切换到已有的选项卡
      						} else if(node.data.menuURL != null && node.data.menuURL != "") {
      							 element.tabAdd('menuTab',{
      		                                    title: node.data.title,
      		                                    content: ''// 支持传入html
      		                                    ,
      		                                    id: node.data.id
      		                                });
      		                            element.tabChange('menuTab', node.data.id);//切换到新加的选项卡
      						}
      					}
      				})
      			}
      		})
      	})
      })

      阅读了layui文档,似乎没有讲到过如何获得动态数据,因此需要先通过ajax请求获得json数

      据,然后在使用。

      后端实现

      项目结构

      EasyUI&Layui树形菜单实现_第9张图片

      1、步骤分析

      ①明白java转换成json对应的格式

      ②分析数据格式得出类:TreeVo

      ③为实现数据结构得出工具类:BuildTree

      ④搭建mvc,配置文件

      ⑤entity、dao、web层的编写

      2、实现

      ①java转换成json

      集合—— [{...},{...},{...}]

      对象—— {...}

      json中的对象是键值对的形式,属性名作为键。

      ②TreeVo.java

      package com.zwf.entity;
      
      import java.util.ArrayList;
      import java.util.List;
      import java.util.Map;
      
      /**
       * 为了方便阅读,构造以及get、set方法以省去
       * 注意:我这是使用了layui,所有节点文本属性为title。EasyUI为text
       * 这里的属性可以比接口数据多,但是为了实现前端效果的基本属性不能少,即文档上的接口数据格式上的属性
       * Menu实体类和数据库字段相同,但是前段的接口数据字段和Menu对象不同,因此需要TreeVo
       */
      public class TreeVo {
      	/**
      	 * 节点ID
      	 */
      	private String id;
      	/**
      	 * 显示节点文本
      	 */
      	private String title;
      	/**
      	 * 节点是否被选中 true false
      	 */
      	private boolean spread = false;
      	/**
      	 * 节点的子节点
      	 */
      	private List> children = new ArrayList>();
      	/**
      	 * 父ID
      	 */
      	private String parentId;
      	/**
      	 * 是否有父节点
      	 */
      	private boolean hasParent = false;
      	/**
      	 * 是否有子节点
      	 */
      	private boolean hasChildren = false;
      	/**
      	 * URL
      	 */
      	private String menuURL ;
      	/**
      	 * 节点属性
      	 */
      	private Map attributes;
      }

      ③BuildTree.java

      com.zking.util;
      
      
      import com.zwf.entity.*;
      
      import java.util.ArrayList;
      import java.util.HashMap;
      import java.util.List;
      import java.util.Map;
      
      /**
       * 直接上手阅读可能会晦涩难懂
       * @author zjjt
       *
       */
      public class BuildTree {
      
      	/**
      	 * 默认-1为顶级节点
      	 * @param nodes 未存在层级结构的所有节点
      	 * @param 
      	 * @return 一个最顶层的TreeVo对象,里面包含所有节点
      	 */
      	public static  TreeVo build(List> nodes) {
      
      		if (nodes == null) {
      			return null;
      		}
              //顶级节点容器
      		List> topNodes = new ArrayList>();
      
              /**
               * 找到children的父节点PID,如果是顶级节点,直接装入到容器中,跳过该次循环。
               * 如果不是说明它有父节点。
               * 那么再次循环所有节点找到parent自己的ID等于children的PID,那么parent就是children的父节点
               * 之后完成相应操作
               */
      		for (TreeVo children : nodes) {//遍历节点集合
      			String pid = children.getParentId();//获得父节点ID
      			if (pid == null || "-1".equals(pid)) {//如果为-1,则该节点为顶级节点
      				topNodes.add(children);//装入顶级节点容器中
      				continue;
      			}
      			
      			for (TreeVo parent : nodes) {//再次遍历节点集合
      				String id = parent.getId();//获得自己的id
      				if (id != null && id.equals(pid)) {//条件成立,parent则为children父节点
      					parent.getChildren().add(children);
      					children.setHasParent(true);
      					parent.setHasChildren(true);
      					continue;
      				}
      			}
      		}
      		/**
      		 * 最顶级节点对象
      		 */
      		TreeVo root = new TreeVo();
      		if (topNodes.size() == 1) {
      			root = topNodes.get(0);
      		} else {
      			root.setId("000");
      			root.setParentId("-1");
      			root.setHasParent(false);
      			root.setHasChildren(true);
      			root.setSpread(true);
      			root.setChildren(topNodes);
      			root.setTitle("顶级节点");
      		}
      		return root;
      	}
      
      	/**
      	 * 指定idparam为顶级节点
      	 * @param nodes
      	 * @param idParam
      	 * @param 
      	 * @return
      	 */
      	public static  List> buildList(List> nodes, String idParam) {
      		if (nodes == null) {
      			return null;
      		}
      		List> topNodes = new ArrayList>();
      
      		for (TreeVo children : nodes) {
      
      			String pid = children.getParentId();
      			if (pid == null || idParam.equals(pid)) {
      				topNodes.add(children);
      				continue;
      			}
      
      			for (TreeVo parent : nodes) {
      				String id = parent.getId();
      				if (id != null && id.equals(pid)) {
      					parent.getChildren().add(children);
      					children.setHasParent(true);
      					parent.setHasChildren(true);
      					continue;
      				}
      			}
      		}
      		return topNodes;
      	}
      }

      可能还是有点不明白,为什么一个最顶级节点就有了所有节点。以下是我自绘的一个类之间的结构图

      EasyUI&Layui树形菜单实现_第10张图片

       根据pid和id两个字段即可实现我们的树形结构!!!数据库表如下

      EasyUI&Layui树形菜单实现_第11张图片

      ④搭建mvc,配置文件

      之前的文章貌似仅仅讲解了mvc的执行流程,和代码。我们可以将之前的那个包打包成jar包来使

      用。这个jar包就是一个非常基础的mvc框架!

      主要分享些注意事项:

      根据mvc的执行流程可以看出,中央控制器可浏览器联系,子控制器和Dao层联系。那么途

      中产生的报错我们也能具体的分区,比如反射调用找不到方法这个错误。首先思考这是在流

      程中的哪一步,中央控制器截取到methodName后面的方法名x,然后就是反射调用子控制器

      的x方法。要么是子控制器没有X方法,要么是mvc.xml中对应的子控制器全路径名配置错

      误,导致不是我们需要的子控制器找不到该方法。

      总结:

      首先是浏览器请求(/book.action?methodName=list)首先进入中央控制器,这里少不了web.xml对中

      央控制器的配置(*.action),然后是通过/book找到模型再拿到具体子控制器路径反射实例化。这里

      少不了mvc.xml对子控制器的配置,然后是反射调用list方法,这里少不了子控制器中拥有该方法。

      然后通过list方法返回的String获得forward模型再获得跳转路径和是否转发条件,这里少不了对

      mvc.xml中forward的配置!

      主要是想表达一点:对一个功能或者程序的执行流程足够了解就能快速定位错误范围,提高解决错

      误效率。

      配置文件:

      
      
      	
      

      ⑤dao层,servlet层

      前端仅需要一个接口,而且接口是json数据,不能通过请求去赋值,js代码是不支持EL表达式的!

      那么这里怎么将数据发送都前台呢?通过response对象!

      MenuDao.java

      package com.dao.zwf;
      
      import java.util.ArrayList;
      import java.util.HashMap;
      import java.util.List;
      import java.util.Map;
      
      import com.zking.util.BaseDao;
      import com.zking.util.BuildTree;
      import com.zking.util.PageBean;
      import com.zking.util.StringUtils;
      import com.zwf.entity.Book;
      import com.zwf.entity.Menu;
      import com.zwf.entity.TreeVo;
      
      /**
       * Dao层,与数据库交互,获得需求数据
       * @author zjjt 隔壁程序员老张
       *
       */
      public class MenuDao extends BaseDao{
      	
          /**
      	 * 
      	 * @param m 菜单对象
      	 * @param pageBean 分页对象
      	 * @return  所有菜单,并不具备层级结构
      	 * @throws Exception 抛出所有异常
      	 */
      	public List list(Menu m, PageBean pageBean) throws Exception {
      		String sql="select * from t_easyui_menu";
      		return super.executeQuery(sql, Menu.class, null);
      	}
      	
          /**
      	 * 
      	 * @param menu 菜单对象
      	 * @param pageBean 分页对象
      	 * @return 具备层级结构的TreeVo集合
      	 * @throws Exception
      	 */
      	public List> tree(Menu menu, PageBean pageBean) throws Exception{
      		List list = this.list(menu, pageBean);//先查出所有菜单
      		List> li = new ArrayList>();
      		for (Menu m : list) {//将所有Menu转换成TreeVo
      			TreeVo t = new TreeVo();
      			t.setId(m.getMenuid());
      			t.setTitle(m.getMenuname());
      			t.setParentId(m.getParentid());
      			t.setMenuURL(m.getMenuURL());
      			Map attr = new HashMap();
      			attr.put("self", m);
      			t.setAttributes(attr);
      			li.add(t);
      		}
      		return BuildTree.buildList(li, "000");//返回具备层级结构的TreeVo集合
      	}
      }

      MenuAction.java

      package com.web.zwf;
      
      import java.util.List;
      
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;
      
      import com.dao.zwf.MenuDao;
      import com.fasterxml.jackson.databind.ObjectMapper;
      import com.zking.framework.ActionSupport;
      import com.zking.framework.ModelDriver;
      import com.zking.util.BuildTree;
      import com.zking.util.ResponseUtil;
      import com.zwf.entity.Menu;
      import com.zwf.entity.TreeVo;
      
      /**
       * Tree组件数据接口
       * @author zjjt 隔壁程序员老张
       *
       */
      public class MenuAction extends ActionSupport implements ModelDriver{
      	
      	private Menu m = new Menu();
      	private MenuDao md = new MenuDao();//dao层
      	
      	@Override
      	public Menu getModel() {
      		return m;
      	}
          
      	/**
      	 * @param req  请求对象
      	 * @param resp 响应对象
      	 * @return null
      	 */
      	public String list(HttpServletRequest req, HttpServletResponse resp) {
      		try {
      			List> tree = md.tree(null, null);//获取具备层级结构的TreeVo集合
      			ResponseUtil.writeJson(resp, tree);//通过Response打印JSON数据给前端
      		} catch (Exception e) {
      			e.printStackTrace();
      		}
      		return null;
      	}
      	
      }

      工具类RespnseUtil.java

      package com.zking.util;
      
      import java.io.PrintWriter;
      
      import javax.servlet.http.HttpServletResponse;
      
      import com.fasterxml.jackson.core.JsonProcessingException;
      import com.fasterxml.jackson.databind.ObjectMapper;
      
      public class ResponseUtil {
      	
          /**
           * 通过out对象打印JSon数据给前端
           */
      	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();//JSON工具包中的对象,将o转换成JSON格式
      		write(response, om.writeValueAsString(o));
      	}
      	
      }

      ⑥测试

      总结:

      核心还是在于TreeVo和BuildTree。其他步骤的小细节不可忽略。

      你可能感兴趣的:(easyui,layui,jquery)