目录
一、概念
二、为什么学习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,免费文档不齐全。
从界面效果上来讲比bootstrap和layui都要差!
但是从学习文档的完整性,前端框架的稳定性,组件的丰富性考虑,EasyUI优于layui。本人第一
次接触使用的前端框架是layui,学习起来挺吃力。我觉得这个是要不断积累的过程,在已经有前端
框架的学习经验上去学习新的框架会比第一次接触轻松许多!一定要掌握好学习方法!EasyUI的
文档很齐全,非常适合入门学习。当然选择什么框架进行开发,从公司的角度出发:成本、公司的
后端技术人员前端功底、前端的社区活跃度。
首先看说明文档:
说明了在使用它的组件时,属性、事件、方法定义在那里。这是EasyUI的一个使用规范。不同的
框架会有不同的使用规范。
我们需要使用EasyUI,就必须导入它的css,js文件。
这里需要注意一点,EasyUI.js是基于jQuery之上的。js是一门语言,而jQuery是js的框架,
jQuery对js进行封装,EasyUI.js则是使用jQuery编写出来的。所以EasyUI.js是依赖与jQuery
的。
这里使用到了组件:layout
,tree
,tabs
还有更多的使用方式,这里仅仅截取部分,全内容看文档!
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的数据接口格式:
通过这个结构是否能想到我们用来接收数据的类
结构?
效果图:
没有花时间去写css样式了,简单的效果展示!
<%@ 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
$(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数
据,然后在使用。
①明白java转换成json对应的格式
②分析数据格式得出类:TreeVo
③为实现数据结构得出工具类:BuildTree
④搭建mvc,配置文件
⑤entity、dao、web层的编写
①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;
}
}
可能还是有点不明白,为什么一个最顶级节点就有了所有节点。以下是我自绘的一个类之间的结构图
根据pid和id两个字段即可实现我们的树形结构!!!数据库表如下
④搭建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
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。其他步骤的小细节不可忽略。