1 概述
本文档内容包括easyui的引入和easyui的使用实践,编写该文档的目的,其一是为了下次再使用easyui的时候,有章可循,提高开发效率;其次记录使用过程中遇到的一些关键的问题,供自己和其他的同学参考。
2 EasyUI的引入说明
Jquery库引用
EasyUI中自带了Jquery的库,版本是V2.0.0,请注意该版本不一定适用于你的项目场景,关于JqueryV2.0.0对IE浏览器的支持也是每一个开发人员需要注意的。
Jquery V2.0.0支持IE9+。
最新的不一定是最好的,有时候,请果断更换你的jquery版本。
还有一点注意的是,项目中通常不会只有一个地方使用jqeury,使用easy ui时,使用项目中统一的jquey版本库,也不失为一种好的方案。
关于easyui包目录结构调整说明
通常从jquery-easyui官网中下载下来的包,是一个相当完整的包:其目录结构如下:
其中:
- demo目录是easyui使用示例;
- locale目录是国际化支持;
- src目录是部分easyui插件的源码;
- plugins目录是easyui使用的插件;
- themes目录包含多套easyui可使用的主题。
通常在项目中使用的话,demo目录、src目录可以不用,locale可以去除没用的js库,主题如果只使用默认的主题,也可以去除不用的主题。项目中,清理后的easyui目录结构参考如下:
其中extends目录是项目中,基于easyui框架做的一些扩展。
使用easyui需要引用的js和css
这次项目中主要为了使用easyui的datagrid控件,才引入了easyui框架。由于不同的模块都会使用的easyui,所以把easyui相关的js和css统一放到了editInclude.jsp页面中,editInclude.jsp页面的内容如下:
page contentType="text/html; charset=gbk" language="java" %> String webContext = request.getContextPath(); %> k rel="stylesheet" type="text/css" href="%=webContext %>/js/jquery-easyui/themes/gray/easyui.css"> k rel="stylesheet" type="text/css" href="%=webContext %>/js/jquery-easyui/themes/icon.css"> ipt type="text/javascript" src="ext %>/js/jquery/jquery-1.7.2.min.js"> ipt type="text/javascript" src="ext %>/js/jquery-easyui/jquery.easyui.min.js"> ipt type="text/javascript" src="ext %>/js/jquery-easyui/locale/easyui-lang-zh_CN.js"> ipt type="text/javascript" src="ext %>/js/jquery-easyui/extends/easyui.formatter.js"> ipt type="text/javascript" src="ext %>/js/jquery-easyui/extends/easyui.edit.js"> |
Js和css文件说明:
- easyui.css是easyui框架的主样式;
- icon.css是easyui中用到的图标的样式;
- jquery-1.7.2.min.js是easyui使用的基础;
- jquery.easyui.min.js是easyui的核心javascript库;
- easyui-lang-zh_CN.js是easyui对中文的国际化支持;
- easyui.formatter.js和easyui.edit.js是项目中使用到的两个扩展js库。
3 关于easyui控件的使用
easyui库作为一个相对成熟的js前端框架,提供了非常丰富的UI控件,包括form表单控件、layout布局控件、gird控件等等。
这里对使用easyui控件过程中的一些注意事项进行说明。
控件组成部分
每一个easyui控件通常都是由属性(Properties)、事件(Events)和方法(Methods)这些组成部分。
控件自身用到的信息可以通过属性存储,控件可以利用某些属性(比如url)完成特定的操作;控件基于事件驱动,开发人员可以在控件初始化的时候,为控件绑定一些特定事件(比:form的onSubmit事件);easyui为每个控件提供了操作控件相关内容的函数,每个函数对应特定的功能(比如:datagrid的options方法,可以获取datagrid控件的属性设置)。下面是一个简单的例子:
Form |
上面列出了form控件的属性列表和事件列表。
小贴士:对控件属性、事件、方法的理解,可以参考HTML的input元素(有属性、事件)。
控件的继承特性
在easyui中使用了继承特性,在定义了一部分基础控件的基础上(比如:tree、combo等),可以扩展出功能更完善的控件,比如:基于combo的扩展combotree、combogrid、combobox,基于panel的扩展有tab、layout、Accordion等。
Easyui控件的继承特性,在父控件中定义的属性适用于子控件,比如有这么一个业务场景,combobox中输入框默认是可以编辑,在我们的业务上需要屏蔽对combobox的编辑功能。针对刚才的业务场景,我们去查看combobox的属性(通常控件的属性可以对控件进行控制),但是在combobox的一堆属性中没有一个可以用于控制输入框的编辑性。不过由于easyui控件拥有继承特性,父控件中定义的属性适用于子控,所以可以查看combobox继承了哪些控件,API告诉我们combobox继承了combo这个控件,同时combo的属性中有editable这一项,专门用于控制编辑框的可编辑性,所以easyui控件的继承特性很好的解决了我们项目中遇到的问题。
对于控件的继承特性中,属性的继承是用得比较多的,关于事件和方法的继承,个人觉得是支持的,不过没有实践。
调用控件的方法
Easyui控件在初始化之后,javascript语言中对控件的操作通过控件相关的方法完成。
下面通过combobox控件来说明怎样来调用控件的方法:
var options = $(“#datagrid”).datagrid(“options”); | | | A B C 说明如下 上面的代码可以分成三部分解读: A:通常每个控件都会有一个ID属性,通过Jquery获取到datagrid对象; B:通常该部分对应控件的名字; C:参数是控件中提供的方法名。 |
修改控件的属性
Easyui中控件初始化时,所有的初始化信息(包括属性的值、事件对应调用函数)都存储在一个javascript对象中,基本上所有的控件都提供了一个方法“options”,通过这个方法可以获取到这个对象。下面的例子是修改datagrid控件的url属性:
var options = $(“#datagrid”).datagrid(“options”); options.url = “targetUrl”; |
说明:easyui控件的属性都可以作为options的属性来操作,达到修改的目的,特别说明,对datagrid控件的url属性的修改会触发一次datagrid的远程调用。
控件事件的注册
Easyui控件支持事件,当相应的操作触发时,可以调用特定的函数,完成自定义的处理动作。
下面的几个例子用来说明怎么注册:
例子一在初始化tab控件的时候注册onSelect事件
普通的HTML代码 --> id="baseTab" > id="matter" title="111" selected="true"> |
id="object" title="222">
id="project" title="333">
v>
Js处理脚本-->
ipt type="text/javascript">
$(function(){
var selectedIndex = -1;
$('#baseTab').tabs({
border:false,
plain:true,
fit:true,
tools:'#tab-tools',
onSelect:function(title,index){
localSearch();
}
});
});
ript>
说明如下
上面的HTML代码没有任何特别之处,着重解释js初始化的动作。
上面的js代码可以分成两部分:$('#baseTab').tabs()和{border:false,…},两部分的结合使用代表tab控件的初始化,tabs方法的参数是一个javascript对象,如上所说,在该对象中就包括了对tabs控件属性的赋值,比如border的值false;以及注册了onSelect事件,其中函数的参数,在easyui提供的api中有说明。
例子二在HTML中为Editor注册onSelect事件
普通的HTML代码 --> |
ditor='{type:"combobox",options:{onSelect:onSelectOperateType,valueField:"itemValue",textField:"itemName",data:}}'data-options="field:'operateType' ">操作类别 |
---|
Js处理脚本-->
pt type="text/javascript">
function onSelectOperateType(){
//处理过程
}
ipt>
说明如下
HTML中为Editor控件注册了onSelectOperateType,同时需要在script脚本中提供该函数。
例子三初始化datagrid后注册onDblClickCell事件
代码 --> table.datagrid({ onDblClickCell:function(rowIndex,field,value){
} }); 说明如下 同js初始化控件一样,不过在函数对应的参数中,只指定了要注册的事件。 |
4 关于Combobox的使用_wangxz
示例:input
问题:二次加载
下拉项数据加载:loadData,url
常用事件注册,onSelect,级联操作
常用属性设置:width、panelWidth、editable
常用方法:setValue、getValue、enable、options
示例代码
Select创建
- id="cc" class="easyui-combobox" name="dept" style="width:200px;">
- value="aa">aitem1
- bitem2
- bitem3
- ditem4
- eitem5
Input创建
- id="cc" class="easyui-combobox" name="dept"
- data-options="valueField:'id',textField:'text',url:'get_data.php'" />
使用javascript脚本创建
- id="cc" name="dept" value="aa">
- $('#cc').combobox({
- url:'combobox_data.json',
- valueField:'id',
- textField:'text'
- });
创建2个有依赖关系的下拉列表框。
- id="cc1" class="easyui-combobox" data-options="
- valueField: 'id',
- textField: 'text',
- url: 'get_data1.php',
- onSelect: function(rec){
- var url = 'get_data2.php?id='+rec.id;
- $('#cc2').combobox('reload', url);
- }" />
- id="cc2" class="easyui-combobox" data-options="valueField:'id',textField:'text'" />
常用属性
Data属性 通过一个对象数组初始化下拉combobox的数据
data: [{
label: 'java',
value: 'Java'
},{
label: 'perl',
value: 'Perl'
},{
label: 'ruby',
value: 'Ruby'
}]" />
Url属性 通过一个url地址 返回个个json对象数组初始化数据
url: '/hr/emp/abc.js'" />
valueField属性 下拉项对象的提交到后台的值
textField属性 用于显示下拉项的文本
Formatter属性 用户格式化数据的显示
常用事件
onSelect 下拉框的选择事件
代码 --> tid="empInfoVOpostName" data-options="valueField:'content',editable:false,onSelect:selectPostName,textField:'name',url:'/otherbusiness/hr/emp/empInfo.do?method=postNameDetailJson'" class="easyui-combobox"> function selectPostName(rec){ $("#empInfoVO\\.postName").val(rec.content); $("#empInfoVO\\.postRank").val(rec.postRankId); $("#empInfoVOpostRank").combobox("setValue",rec.postRankId); $("#empInfoVO\\.postType").val(rec.postTypeId); if(rec.postTypeId===EmpConstant.POST_TYPE_LEADER%>){ $("#showempInfoVO\\.postType").html("领导"); }else if(rec.postTypeId==ST_TYPE_NOTLEADER%>){ $("#showempInfoVO\\.postType").html("非领导"); }else if(rec.postTypeId==ST_TYPE_NOT%>){ $("#showempInfoVO\\.postType").html("不确定"); }else{ $("#showempInfoVO\\.postType").html(""); } } 说明如下 |
常用方法
getData 获取加载的数据
setValue 设置下拉列表框的值。 选中的值
常见问题
不会的问题:
1、要求combobox支持拼音查询,比如民族 输入hanzu出现汉族怎么做?
5 关于Datagrid
Datagrid中列表宽度的设置建议
Datagrid的column有width属性,说明column是可以精确的指定列的宽度,极端的做法是每列指定具体的值,但是通常不建议这么做。
建议的做法,预留一列不设置width属性,系统会为其他列分配宽度后,将剩余的宽度留给该列,注意一点:未设置列宽的column其具体的width值未知,但是大概可以判断出他的值,根据业务需要,决定是否设置具体的width。
关于editor的使用说明
Easyui支持可编辑的datagrid控件,其中datagrid中行(row)的可编辑功能通过editor实现。
关于editor的几点说明:
- 可以把editor看成一个控件,他也有一些属于自己的方法,比如getValue、setValue;
- 在指定editor的时候,有两个参数很重要:类型和初始对象,对初始对象的理解可以当成脚本初始化控件中的参数,类型主要指编辑控件的类型,比如text、combobox、combotree等;
- 在指定editor的类型之后,editor就关联了一个target的jquery对象,根据editor的类型,target对象的类型也不一样。有如下规律:如果editor的类型可以对应到easyui中定义的控件,则target就是一个相应类型的easyui控件;特殊的如果editor的类型是text或者numberbox等,对应的target其实就是一个普通的代表input的jquery对象;再有的话,需要根据edtior的具体类型具体判断。
- 在datagrid中,有相应的方法控制一行所有editor的编辑状态,在js脚本中需要获得行eidtor对象时,需要先调用datagrid的beginEdit,打开行编辑;
- js中有两种方法获取单元格对应的editor对象,分别调用datagrid对象的getEditors和getEditor方法,具体使用请参考easyui的API;
- 当editor的target中提供的事件不能满足需要的时候,需要为target对象注册更多的事件,比如为类型为text的editor注册keyup事件,这时候,需要探究target对象的本质(比如:combobox、jquery的input对象等),在此基础上为target绑定事件。
自定义editor
关于插件detailView的使用
关于排序的使用_wangzw
6 关于treegrid的使用
动态加载treegrid数据
7 关于tab的使用
tab-tools的布局
项目中有同学布局没有按照easy ui的方式布局,比如使用如下的方式:
div id="baseTab" class="easyui-tabs" border="false" plain="true" fit="true" style="overflow: no;" tools='#tab-tools'> div title="事项"> iframe id="secretMatter" src="erUrl %>?method=list"style="width: 100%;height: 100%;" frameborder="0" scrolling="no">ame> /div> div id="object" title="111">
/div> div id="project" title="222">
/div> div id="summary" title="333">
/div> div id="tab-tools"> 报表期:donly="readonly" type="text" name="reportPeriod" id="reportPeriod" Usage="empty"> /div> /div> |
使用如下的布局,工具条会照样出来,不过却多了一个tab页
效果如下:
正确的布局方式应该是:
div id="baseTab" class="easyui-tabs" border="false" plain="true" fit="true" style="overflow: no;" tools='#tab-tools'> div title="事项"> iframe id="secretMatter" src="erUrl %>?method=list"style="width: 100%;height: 100%;" frameborder="0" scrolling="no">ame> /div> div id="object" title="111">
/div> div id="project" title="222">
/div> div id="summary" title="333">
/div> /div> div id="tab-tools"> 报表期:input readonly="readonly" type="text" name="reportPeriod" id="reportPeriod" Usage="empty"> /div> |
减少Tab中使用iframe时的请求次数
通过Iframe来组织tab控件标签页的内容是一种常用的方法,直接的好处,使用iframe操作简单,但是简单的同时也可能会造成资源的重复加载这也体现了事物的双面性。当然这些都不是重点,这里提供一种方法,避免tab控件使用iframe时,重复请求数据。
造成tab控件中iframe对此请求数据的原因,大概有以下两种:
1、tab控件中,每个tab页关联一个iframe,tab控件在加载的时候,会依次请求所有iframe中的内容,为了页面的加载速度,通常只需要加载一个iframe就可以了;
2、在使用tab控件的一些方法时,会触发tab控件,更新tab页内容,比如:已经通过html的方法,初始化tab控件,但是在jquery的初始脚本中仍然用$(“#tab”).tabs({…})这种方式操作tab控件,这样会引起iframe内容的重新请求。
多余的资源请求,肯定不是我们想要的,这样造成了网络资源的浪费,也造成了缓慢的页面加载。通过实践,我们使用了如下的方法来解决这个问题:
代码 --> ="loseCaseTab" class="easyui-tabs" border="false" plain="true" fit="true" style="overflow: no;" tools='#tab-tools'> iv id="caseNum" title="失泄密案件数量" selected="true"> ="peopleNum" title="处理责任人数量"> |
处理脚本-->
type="text/javascript">
$(function(){
var selectedIndex = -1;
$('#loseCaseTab').tabs({
border:false,
plain:true,
fit:true,
tools:'#tab-tools',
onSelect:function(title,index){
localSearch();
}
});
//查询
function localSearch(){
var loseCaseTab = $('#loseCaseTab');
var selectedTab = loseCaseTab.tabs("getSelected");
var targetIframe = selectedTab.find("iframe");
//
if(targetIframe.length == 0){
var id = selectedTab.attr("id");
if(id){
if(id == "caseNum"){
selectedTab.append('');
$("#loseCaseNum").attr("src","?query.caseType=&method=list&query.reportPeriod="+$("#reportPeriod").val());
}else if(id == "peopleNum"){
selectedTab.append('');
$("#punitivePeopleNum").attr("src","?query.type=&method=list&query.reportPeriod="+$("#reportPeriod").val());
}
}
}else{
var iframeContents = targetIframe.contents();
var form = iframeContents.find("form");
var queryReportPeriod = iframeContents.find("#query\\.reportPeriod");
queryReportPeriod.val($("#reportPeriod").val());
form.submit();
}
}
});
t>
说明如下
同js初始化控件一样,不过在函数对应的参数中,只指定了要注册的事件。
8 Easyui深度学习
查看easyui解析后的页面元素
为什么会提出这个问题?easyui有着自己的一套解析思路,根据相应的class和js,用自己的方式实现html表单元素的功能。比如:html中的select元素,在easyui中是通过combobox来实现的,在easyui初始化combobox控件后,生成的HTML源码也不再是。
话说回来,查看easyui控件的源码,有助于我们去实现一些特定的效果,比如绑定事件。
个人的习惯是通过chrome开发工具中的“审查元素”功能来查看easyui控件具体的HTML源码;或者也可以使用IE8的开发人员工具中,HTML查看工具来实现该功能。
学习easyui源码的一种方式
Easyui不开源它的源码,不代表我们就没有办法解读它的源码。在深入使用easyui库的时候,有时候也需要我们进一步探究easyui本身的实现机制。
下面介绍一种查看easyui源码的方式:
处理脚本--> type="text/javascript"> $(function(){ var selectedIndex = -1; $('#loseCaseTab').tabs({ //在此处设置断点即可 border:false, plain:true, fit:true, tools:'#tab-tools', onSelect:function(title,index){ localSearch(); } }); }); t> 说明如下 具体的操作方式,通过chrome或者IE的开发人员工具的脚本调试工具来完成。在上面设置断点的地方,首先需要单步进入代码内部,此时会发现其实进入的只是Jquery的源码;接着跳出该函数,调试会回到$('#loseCaseTab').tabs,这步很重要,跳出没必要的执行步骤;继续单步进入,这时候进来的才是easyui的源码。同时你会发现easyui做过一些处理,函数名称和变量名称基本上没任何意义,所以解读easyui的源码也算是一个枯燥的事情。 |
9 常见问题
My97DatePicker报“权限错误”问题
当同时使用easyui和My97DatePicker两个组件的时候,很有可能会遇到“权限错误”的问题。
问题可以定焦在easyui中有些控件中会自动通过iframe来加载内容有关,但是怎么会出现跨域问题,个人也没理解,但是这里给出解决问题的办法:
对WdatePicket.js中的$crossFrame:true做出修改,true改为false。 |
表单数据提交
通常前台表单的提交都是使用form表单元素,在form中会有很多的input或者其他的输入表单元素,不知道你遇到过这类情况没有,前台页面写法如下:
java后台通过getParameter时,获取不到createDate修改后的值。
原因是因为不在form内部的表单元素是不会被传入后台的,所以在java后台获取不到createDate的值。
正确的写法是:
Datagrid的重复加载问题
为numberbox设置maxlength属性
延迟detailview加载
Datagrid横向滚动条设置
Datagrid异步提交问题
Datagrid列表中数据字典显示问题
通过脚本自动生成formatter函数
editor类型为datebox,endEditor后显示的时间格式_wangzw