EasyUI 官方网站:http://www.jeasyui.com/index.php
EasyUI API:http://www.jeasyui.com/documentation/index.php
最近使用JQuery的EasyUI进行对表格进行CRUD操作,看到官网上的示例演示特别简单,但是在实际操作中发现并没有那么简单。以下就是在自己写的时候出现的一些问题。
UI页面如下:
这个示例有三个页面:
主页面:easyui_exercise.html:
<!DOCTYPE html>
<html lang = "en">
<head>
<meta charset = "UTF-8">
<title>Title</title>
<link rel = "stylesheet" type = "text/css" href = "easyui/themes/default/easyui.css">
<link rel = "stylesheet" type = "text/css" href = "easyui/themes/icon.css">
<script type = "text/javascript" src = "js/jquery-2.1.4.min.js"></script>
<script src = "easyui/jquery.easyui.min.js"></script>
<script src = "easyui/easyui-lang-zh_CN.js"></script>
<script src = "easyui/jquery.edatagrid.js"></script>
<script src = js/datepicker/WdatePicker.js></script>
</head>
<style>
#memo_id p {
padding-left: 10px;
}
</style>
<script>
$(function () {
$("#sys_mng_id div:first a").click(function () {
if ($("#tabs_id").tabs("exists", $(this).text())) {
$("#tabs_id").tabs("select", $(this).text());
} else {
$("#tabs_id").tabs("add", {
title: $(this).text(),
selected: true,
closable: true,
content: $(this).text()
})
}
});
$("#tabs_id").tabs({
// tools: [{
// iconCls: "icon-add",
// handler: function () {
// alert("添加");
// }
// }, {
// iconCls: "icon-save",
// handler: function () {
// alert("正在保存");
// }
// }],
onBeforeClose: function (title) {
return window.confirm("您确定要关闭 " + title + " 选项卡吗?");
}
});
})
</script>
<body class = "easyui-layout">
<div data-options = "region:'north',split:false,border:false" style = "height:15%;text-align: center;">
<h1>初次学习JQuery组件--EasyUi</h1>
</div>
<div data-options = "region:'south',split:false,border:true" style = "height:5%;text-align: center">©Flying版权所有
</div>
<div id = "memo_id" data-options = "region:'east',title:'备注',split:false,collapsible:true,border:false"
style = "width:20%;">
<h1 style = "text-align: center">今天新闻</h1>
<p>网站建设中...</p>
<p>网站建设中...</p>
<p>网站建设中...</p>
<p>网站建设中...</p>
<p>网站建设中...</p>
<p>网站建设中...</p>
</div>
<div id = "sys_mng_id" class = "easyui-accordion" data-options = "
region:'west',title:'系统菜单',split:false,collapsible:true,selected:-1,multiple:false,border:false"
style = "width:20%;overflow: auto">
<div title = "部门管理"
data-options = "iconCls:'icon-save',href: 'http://localhost:8080/SSMProjectMaven/tree.html'"></div>
<div title = "人事管理" data-options = "iconCls:'icon-reload'">此处内容</div>
<div title = "客户管理" data-options = "iconCls:'icon-remove'">此处内容</div>
<div title = "权限管理" data-options = "iconCls:'icon-edit'">此处内容</div>
<div title = "报表管理" data-options = "iconCls:'icon-print'">此处内容</div>
<div title = "帮助" data-options = "iconCls:'icon-help'">此处内容</div>
</div>
<div id = "tabs_id" data-options = "region:'center',border:false"
style = "padding:5px;background:#eee;">
</div>
<script>
$(function () {
$("body").layout("panel", "center").panel({
href: "http://localhost:8080/SSMProjectMaven/student.html"
});
})
</script>
</body>
</html>
在我是把student.html和tree.html页面嵌入到该主页面中的。
我发现使用EasyUI的panel的href属性嵌入另一个页面时,只会加载href指向页面的body中的内容,
也就是说如果你在子页面中在body之外引入了javascript外部文件,但是在主页面中没有引入该文件,那么该子页面在主页面中将不能正常工作。在body之外设置的CSS属性亦是如此。所以在子页面中设置的CSS属性应该尽量放在body标签内,或者使用内联样式。
子页面(该页面中需要注意的地方已经在代码中注释注明了):student.html
WdatePicker组件的使用参见该篇博客:http://my.oschina.net/u/2608182/blog/731627
<!DOCTYPE html>
<html lang = "en">
<head>
<meta charset = "UTF-8">
<title>Title</title>
<link rel = "stylesheet" type = "text/css" href = "easyui/themes/default/easyui.css">
<link rel = "stylesheet" type = "text/css" href = "easyui/themes/icon.css">
<script type = "text/javascript" src = "js/jquery-2.1.4.min.js"></script>
<script src = "easyui/jquery.easyui.min.js"></script>
<script src = "easyui/easyui-lang-zh_CN.js"></script>
<script src = "easyui/jquery.edatagrid.js"></script>
<script src = js/datepicker/WdatePicker.js></script>
</head>
<body>
<style>
#dlg div {
margin-top: 10px;
}
#search_form input {
border-radius: 5px;
border: 1px solid #95B8E7;
height: 20px;
}
</style>
<table id = "dgg"></table>
<div id = "dlg" style = "text-align: center">
<form id = "search_form">
<div>
<label for = "name">姓名:</label>
<input type = "text" id = "name" class = "easyui-textbox" data-options = "required:false">
</div>
<div>
<label for = "birthday">生日:</label>
<!--
这里感觉EasyUI的datebox插件不好用故使用了WdatePicker插件
-->
<input id = "birthday" class = "Wdate"
onfocus = "WdatePicker({
skin:'whyGreen',
isShowWeek:false,
readOnly:true,
highLineWeekDay:true,
dateFmt:'yyyy-MM-dd'})">
</div>
</form>
</div>
<script>
$(function () {
$("#dlg").dialog({
title: "搜索",
closed: true,
modal: true,
width: 300,
height: 150,
buttons: [{
iconCls: "icon-search",
text: "搜索",
handler: function () {
$("#dgg").edatagrid("load", {
name: $("#name").val(),
/*
Tips:
这里需要注意,如果是使用EasyUI的datebox插件的话,
$("#birthday").val()这句代码将取不出来值,
要取出值必须使用以下语句:
$("#birthday").datebox("getValue");
如果使用WDatePicker插件的话不存在这个问题
*/
birthday: $("#birthday").val()
});
$("#dlg").dialog("close");
}
}, {
iconCls: "icon-cancel",
text: "取消",
handler: function () {
$("#dlg").dialog("close");
}
}]
});
$("#dgg").edatagrid({
title: '学生信息',
/*
Tips:
* 这里如果要使用edatagrid插件自带的saveRow,distroyRow等类似方法的话,
* idField属性必须指定,否则在使用这些方法的时候插件将不会自动发送主键
* (例如这里我设置的是Student类的属性sid作为数据库里的主键)参数到服务器,
* 经过测试,貌似插件根本不会向服务器发送请求,除非这里指定了idField属性
* */
idField: 'sid',
fit: true,
method: "GET",
url: "http://localhost:8080/SSMProjectMaven/student/ajax_page.do",
columns: [[
/*
* 该列将显示以多选框形式显示
* */
{field: 'sid', checkbox: true},
{
field: 'name', title: 'name', sortable: false, align: "center", width: 50,
editor: {
type: 'validatebox',
options: {
required: true
}
}
},
{
field: 'birthday', title: 'birthday', align: "center", width: 50,
editor: {
type: 'datebox',
options: {
required: false,
editable: false
}
}
}
]],
toolbar: [{
iconCls: 'icon-add',
text: "添加",
handler: function () {
$('#dgg').edatagrid('addRow');
}
}, '-', {
iconCls: 'icon-save',
text: "保存",
handler: function () {
$('#dgg').edatagrid('saveRow');
}
}, '-', {
iconCls: 'icon-undo',
text: "撤销当前编辑行",
handler: function () {
$('#dgg').edatagrid('cancelRow');
}
}, '-', {
iconCls: 'icon-remove',
text: "删除选中行",
/*
Tips:
* 这里的删除记录我没有选择使用edatagrid插件自带的destroyRow方法,
* 原因是我发现如果我选择了多条记录同时删除的话,例如我选择了10条记录
* 选择删除,该插件就会向服务器发送10次请求,每个请求都附带一个idField
* 属性设置的sid,不能实现一次请求批量删除记录,大大增加了服务器的压力。
* 我这里实现的是一次请求向服务器发送所有用户选择的记录的sid,后台实现
* 记录批量删除。
* */
handler: function () {
var rows = $('#dgg').edatagrid('getChecked');
if (rows.length == 0) {
$.messager.alert("警告", "您没有选择任何行", 'warning');
return false;
}
$.messager.confirm("确认", "您确定要删除已经选择的 " + rows.length + " 行吗?", function (flag) {
if (flag) {
var indexs = [];
for (var i = 0; i < rows.length; i++) {
indexs.push(rows[i].sid);
}
$.ajax({
url: "http://localhost:8080/SSMProjectMaven/student/deletes.do",
type: "GET",
/*
* Tips:
* 这里真的要注意了,费了我好长时间解决这个问题。
* 这里的data就是要向服务器发送的参数,这里由于
* idss的值是一个数组,如果data属性的设置如下:
* data:{'idss':indexs}
* JQuery在解析这个Json对象的时候向服务器最终发送的参数如下:
* 解析之后的参数(带有中括号[]):idss[]:179,idss[]:195,idss[]:196
* 编码之后的参数(带有"%5B%5D"字符):idss%5B%5D=179&idss%5B%5D=195&idss%5B%5D=196
* 然而我服务器设置的用来接收此参数的变量名是idss啊,
* 并且也不能把变量名设置成idss[]啊。
* 后来经过查看JQuery的API以及查找了网上相关资料,JQuery有如下两个方法
* $("form").serialize(),$.param(),
* serialize方法用于把表单内容序列化为Json数据结构的数据,
* 但是我们想服务器发送参数是用类似于aaa=xxx&bbb=xxx的字符串,
* 所以我们就需要使用$.param()方法把Json对象解析成我们需要的请求格式的字符串。
* 但是$.param()方法有两种用法,
* 1. $.param({'idss': indexs}),这种方法在解析数组的时候将会产生"%5B%5D"的字符
* $.ajax()的data参数使用的就是这种方式。
* 2. $.param({'idss': indexs}, true),这种方法就不会产生"%5B%5D"字符这样的问题,
* 解析出来的参数就是我们需要的格式:idss=179&idss=195&idss=196
* 由于$.ajax()的data参数默认使用第一种方式解析Json对象,所以我们就只有
* 手动调用JQuery的$.param()函数来解决"%5B%5D"字符问题
* */
data: $.param({'idss': indexs}, true),
dataType: "json",
success: function (data) {
if (data.status == 1) {
/*
Tips:
* 下面紧接着的一小段被我注释掉的代码也需要注意一下。
* 举个例子:
* 假如rows数组里包含了5条行数据,那么rows的下标就是从0到4.
* 下标依次对应于表格里的第1至5条行数据,当我调用了以下这个方法
* $('#dgg').edatagrid("deleteRow", 0)
* 我移除掉了表格里的第一条行数据,那么同时rows数组的rows[0]对象
* 也会被移除掉,这时rows数组的长度也会减1,下标变成从0到3,
* 在这种情况下若使用如下代码:
* for (var i = 0; i < rows.length; i++) {
* var rowIndex = $('#dgg').edatagrid("getRowIndex", rows[i]);
* $('#dgg').edatagrid("deleteRow", rowIndex);
* }
* 将不会移除掉表格里的起初的第1至5条数据,只会移除掉表格里的第1,3,5条数据,
* 第2,4条数据不会被移除,但实际上数据库里的记录是被删除掉的。
* 使用如下注释掉的代码即可解决该问题。
* 但是这里我选择了调用$("#dgg").edatagrid("reload")这个方法重载当前页
* */
// var n = rows.length;
// for (var i = 0; i < n; i++) {
// var rowIndex = $('#dgg').edatagrid("getRowIndex", rows[0]);
// $('#dgg').edatagrid("deleteRow", rowIndex);
// }
$("#dgg").edatagrid("reload");
}
$.messager.alert("提示", data.msg, 'info');
},
error: function () {
$.messager.alert("错误", "删除失败", 'error');
}
});
}
});
}
}, '-', {
iconCls: 'icon-search',
text: "查找",
handler: function () {
$("#search_form").form("clear");
$("#dlg").dialog("open");
}
}],
/*
* 因为没有使用edatagrid自带的destroyRow方法所以以下紧接着的注释掉的代码
* 也没有用了。
* PS:同时感觉自带的方法灵活性不够,限制太多。
* */
// destroyMsg: {
// norecord: { // 在没有记录选择的时候执行
// title: '警告',
// msg: '当前没有选择任何行'
// }
// ,
// confirm: { // 在选择一行的时候执行
// title: '确认',
// msg: '您确定要删除选中行?'
// }
//
// },
checkOnSelect: false,
selectOnCheck: false,
rowStyler: function (index) {
if (index % 2 != 0) {
return "background-color:#E0E3E6";
}
}
,
fitColumns: true,
singleSelect: true,
pagination: true,
pageList: [10, 20, 30, 50],
pageSize: 10,
rownumbers: true,
saveUrl: "http://localhost:8080/SSMProjectMaven/student/ajax_add.do",
updateUrl: "http://localhost:8080/SSMProjectMaven/student/update.do"
// destroyUrl: "http://localhost:8080/SSMProjectMaven/student/delete.do"
});
$("#dgg").edatagrid("getPager").pagination({
layout: ['list', 'first', 'prev', 'links', 'next', 'last', 'sep', 'refresh']
});
})
</script>
</body>
</html>
子页面tree.html
<!DOCTYPE html>
<html lang = "en">
<head>
<meta charset = "UTF-8">
<title>Tree</title>
<link rel = "stylesheet" type = "text/css" href = "easyui/themes/default/easyui.css">
<link rel = "stylesheet" type = "text/css" href = "easyui/themes/icon.css">
<script type = "text/javascript" src = "js/jquery-2.1.4.min.js"></script>
<script src = "easyui/jquery.easyui.min.js"></script>
<script src = "easyui/easyui-lang-zh_CN.js"></script>
</head>
<body>
<ul id = "tt"></ul>
<script>
$(function () {
$("#tt").tree({
animate: true,
lines: true,
url: "http://localhost:8080/SSMProjectMaven/node/findAllTopRoot.do",
method: "GET",
onlyLeafCheck: true,
checkbox: true,
onLoadError: function () {
alert("加载失败");
}
}
);
})
</script>
</body>
</html>
我们在使用EasyUI时,插件的加载都可以使用HTML方式加载,或者使用JavaScript代码加载,当我们使用HTML加载时,需要在容器中添加类似easyui-xxxx的类ID,当我们使用纯JavaScript代码加载时应尽量不要在容器中添加类似easyui-xxxx的类ID。否则在某些情况下将会出现问题。
举个例子如下:
<table id = "dgg" class = "easyui-edatagrid"></table><!--注意这里我添加了一个"easyui-edatagrid"类ID-->
<script>
$(function () {
//这里又通过使用JavaScript代码加载插件
$("#dgg").edatagrid({
//一系列的属性设置
})
//当我们需要自定义表格的pagination时,如下
$("#dgg").edatagrid("getPager").pagination({
layout: ['list', 'first', 'prev', 'links', 'next', 'last', 'sep', 'refresh']
});
</script>
当我们将该页面通过另一个页面的panel的href属性嵌入到panel中时,以下的这段代码将会失效:
$("#dgg").edatagrid("getPager").pagination({
layout: ['list', 'first', 'prev', 'links', 'next', 'last', 'sep', 'refresh']
});
但是如果我们单独打开这个子页面时,以上的那段代码是有效的。真不知道这是不是一个Bug。
解决方式就是去除这个类ID(在使用纯JavaScript加载插件的情况下才去除,若使用HTML方式加载请加上这个类ID):
class = "easyui-edatagrid"
剩下的就是对Tree这个插件讲一下。
如下这段代码:
<!--这里给div添加了一个样式-->
<div style="text-align:center"><ul id = "tt"></ul></div>
<script>
$(function () {
$("#tt").tree({
animate: true,
lines: true,
url: "http://localhost:8080/SSMProjectMaven/node/findAllTopRoot.do",
method: "GET",
onlyLeafCheck: true,
checkbox: true,
onLoadError: function () {
alert("加载失败");
}
}
);
})
</script>
给Tree的容器div添加了如下的样式:
text-align:center
产生的效果如下(父节点与子节点错位):
而实际的情况应如下:
解决方式就是去掉容纳Tree的容器div的如下的CSS样式,即可恢复正常:
text-align:center
EasyUI 官方网站:http://www.jeasyui.com/index.php
EasyUI API:http://www.jeasyui.com/documentation/index.php