Ext入门学习
一:Ext是什么
ExtJS是一个javascript框架,用于在客户端创建丰富多彩的web应用程序界面。ExtJS 可以用来开发RIA也即富客户端的AJAX应用。
ExtJs最开始基于YUI技术,由开发人员Jack Slocum开发,通过参考Java Swing等机制来组织可视化组件。
二:Ext能干什么
主要是用来制作富客户端的Web应用。包括但不限于:
(1)可以动态创建web组件,动态维护web的Dom对象
(2)灵活地获取界面组件对象,方便对对象的操作和控制
(3)大量的组件对象帮助构建复杂的web应用
(4)友好的Ajax支持
(5)完善的事件处理机制
三:Ext有什么
四:Ext的HelloWorld
1:环境准备
(1)到官网上下载最新的版本,目前是ext-3.3-beta
(2)下载后解压后,看看里面的包结构:
adapter:负责将里面提供的第三方底层库(包括Ext自带的底层库)映射为Ext所支持的底层库。
build:压缩后的ext全部源码(里面分类存放)。
docs: API帮助文档。
exmaples:提供使用ExtJs技术做出的小实例。
resources:Ext UI资源文件目录,如CSS、图片文件都存放在这里面。
package:按包分类的源码
source:无压缩Ext全部的源码(里面分类存放) 遵从Lesser GNU (LGPL)开源的协议。Ext-all.js:压缩后的Ext全部源码。
ext-all-debug.js:无压缩的Ext全部的源码(用于调试)。
ext-core.js:压缩后的Ext的核心组件,包括sources/core下的所有类。
ext-core-debug.js:无压缩Ext的核心组件,包括sources/core下的所有类。
(3)开发的时候只需要把resources包中的css和images放到common下面,还有把ext-all.js和adapter/ext/ext-base.js放入到js中就可以了
2:HelloWorld.html
Ext.onReady(function(){
alert("Hello Ext3.0,你好");
});
五:Ext的面向对象简介
//相当于Java的package
https://www.sodocs.net/doc/376585440.html,space("https://www.sodocs.net/doc/376585440.html,");
//完全使用Ext的创建对象语法太繁琐,还是用我们熟悉的js的语法来写
https://www.sodocs.net/doc/376585440.html,.Class1=function(){
this.aa = "cc";
this.t1=function(){
this.aa="t1";
};
};
https://www.sodocs.net/doc/376585440.html,.Class2=function(){
this.t1=function(){
this.aa="cc2 tt2";
};
};
//表示Class2继承Class1,这里面没有采用Ext的extends
https://www.sodocs.net/doc/376585440.html,.Class2.prototype=new https://www.sodocs.net/doc/376585440.html,.Class1();
//或者使用这个Ext提供的语法
//Ext.extend(https://www.sodocs.net/doc/376585440.html,.Class2,https://www.sodocs.net/doc/376585440.html,.Class1);
//这个是Ext可以给一个对象动态的追加属性和方法
Ext.apply(https://www.sodocs.net/doc/376585440.html,.Class1.prototype,{bb:"bb",cc:"cc",dd:function(){alert("ddd")}} );
六:如何获取界面上的元素——Ext的选择器
1:Ext.Element:Ext的核心对象,是Ext的基础。
Element包含了常见的DOM方法和属性,提供一个快捷的、统一的、跨浏览器的接口(若使用Element.dom的话,就可以直接访问底层DOM的节点。);
2:Ext.get(要获取对象的id)
Element.get()方法提供内置缓存(Cache),多次访问同一对象效率上有极大优势;
内置常用的DOM节点的动作,并且是跨浏览器的定位的位置、大小、动画、拖放等等(添加/移除 CSS 类, 添加/移除事件处理程序, 定位, 改变大小, 动画, 拖放)。
3:获取多个元素——DomQuery
(1)元素选择符selector:
Ext.query(元素类型名称如:”div”);
Ext.query(第一个参数元素类型名称,第二个参数是#元素的id);
Ext.query(#元素的id);
Ext.query(.元素的class);
Ext.query(*号返回所有的元素);
Ext.query("div input")//获取div下的子元素
(2)属性选择符
Ext.query("*[class]")//获取所有有class属性的元素
Ext.query("*[class=hello] )"//获取所有class=hello的元素
Ext.query("*[class!=hello]" )// 获取所有class不等于hello的元素
Ext.query("*[class^=h]" )// 获取所有以h开头的元素
Ext.query("*[class$=h]" )// 获取所有以h结尾的元素
Ext.query("*[class*=hello]" )// 获取所有包含hello的元素
(3)CSS值元素选择符
语法格式:元素{CSS的属性操作符值}
Ext.query("*{color=red}")//获取Css属性中color为red的元素
操作符同样可以是:!=,^,$,*等
(4)伪类选择符
Ext.query("span:first-child"); // SPAN元素为, 其父元素的第一个子元素
Ext.query("a:last-child") //A元素为其父元素的最后一个子元素
Ext.query("span:nth-child(2)") //SPAN元素为其父元素的第2个子元素(由1开始的个数)
Ext.query("tr:nth-child(odd)") //TR元素为其父元素的奇数个数的子元素
Ext.query("li:nth-child(even)") //LI元素为其父元素的偶数个数的子元素
Ext.query("a:only-child") //返回A元素,A元素为其父元素的唯一子元素
Ext.query("input:checked") //返回所有选中的(checked)的INPUT元素
Ext.query("tr:first") //返回第一个的TR元素
Ext.query("input:last") //返回最后一个的INPUT元素
Ext.query("td:nth(2)") //返回第二个的TD元素
Ext.query("div:contains(within)") //返回每一个包含“within”字符串的DIV
Ext.query("div:not(form)") //返回没有包含FORM子元素以外的那些DIV
Ext.query("div:has(a)") //返回包含有A元素的那些DIV集合
Ext.query("td:next(td)") //返回接着会继续有TD的那些TD集合。尤其一个地方是,如果使用了colspan属性的TD便会忽略
Ext.query("label:prev(input)")//返回居前于INPUT元素的那些LABEL元素集合
Ext.query和Ext.select的作用同是根据CSS选择符,基本的XPath,HTML属性等查找出一个或多个元素。区别在于返回类型上。分别是:
query方法返回的是JavaScript标准的数组类型;
select方法返回的是CompositeElement类型,试比较
七:响应事件
Ext.get("btn_add").on("click",function(){alert("哈哈,点击了");});
添加事件方式跟JQuery类似。
如何得知这个event handler执行时是作用在哪一个特定的元素上呢?自动传入event: Ext.get("btn_add").on("click",function(e){alert("哈哈,点击了=="+e.target.value);});
八:数据操作
Store、Record、Reader等
Store是在Js端的小型内存数据中心,js组件从store里面取值
Record是记录,主要就是描述store里面每一条值,基本是key-value
Reader是解析器,就是从原始数据读成需要的对象。
比如:var sexStore = new Ext.data.JsonStore({
url: "a.jsp",
fields: [
'sexTrue', 'sexShow'
],
listeners: {
'load': function(){ alert("now load"); }
}
});
sexStore.load();
后台返回的值:
<%@ page contentType="text/html; charset=gb2312" %>
<%
out.println("[{sexTrue:'1',sexShow:'男人'},{sexTrue:'2',sexShow:'女人'}]"); %>
九:使用组件——Widgets
1:Ext.Button
(1)//初始化
var btn_add = new Ext.Button({
//设置属性
text:"新增",
//显示出来
renderTo:Ext.getBody()
});
(2)//显示按钮的属性,要注意这个text和上面的text在Ext里面不同,上面那个是Config,用在构造对象的时候,这个是属性,用来取值用
alert(btn_add.text);
(3)添加事件:
var btn_add = new Ext.Button({
text:"新增",
renderTo:Ext.getBody(),
handler:function(){
alert("哈哈,点击我");
}
});
handler :用于处理默认的事件,button就是click
还有一种跟swing一样的机制,listeners:
var btn_add = new Ext.Button({
text:"新增",
renderTo:Ext.getBody(),
handler:function(){
alert("哈哈,点击我");
},
listeners:{
"click":function(){
alert("now is click11");
},
"click":function(){
alert("now is click22");
},
"afterrender":function(){
alert("afterrender");
}
}
});
A:可以在listeners里面添加很多事件注册
B:相同的事件,后面的覆盖掉前面的,但不影响handler的触发
还有一种写法:
var btn_add = new Ext.Button({
text:"新增",
minWidth:100,
renderTo:Ext.getBody(),
handler:function(){
alert("哈哈,点击我");
},
listeners:{
"click":function(){
alert("now is click11");
},
"click":function(){
alert("now is click22");
},
"afterrender":function(){
alert("afterrender");
}
}
});
btn_add.on("click",function(){alert("now is click333");});
btn_add.on("click",function(){alert("now is click444");});
A:可以添加很多个,相同的也没有关系,都会运行,形成一个事件链B:可以和handler、listeners共存
2:Ext.form.TextField
Ext.onReady(function(){
var btn_add = new Ext.Button({
text:"新增",
renderTo:Ext.getBody()
});
btn_add.on("click",function(){
alert("now is click444=="+userId.getValue());
}
);
var userId = new Ext.form.TextField({
fieldLabel:"用户编号",
renderTo:Ext.getBody()
});
});
A:会发现:虽然出现了文本框,而且可以操作,点击按钮也能取得文本框的值,但是前面的标签并没有出来,原因是没有使用布局,layout。
这里应该使用https://www.sodocs.net/doc/376585440.html,yout.FormLayout,布局的宿主对象必须是Ext.Container或者其子类。B:只要在构造对象的时候,在宿主对象上指定layout:”form”就好了。
C:Ext.Container的子类主要有:Panel, Toolbar, Viewport, Menu
所以修改成如下:
Ext.onReady(function(){
var btn_add = new Ext.Button({
text:"新增"
});
btn_add.on("click",function(){
alert("now is click444=="+userId.getValue());
userId.setValue("updateddd");
}
);
var userId = new Ext.form.TextField({
fieldLabel:"用户编号",
id:"userId"
});
var addPanel = new Ext.Panel({
renderTo:Ext.getBody(),
layout:"form",
labelWidth:70,
listeners:{
"render":function(addPanel){
addPanel.add(userId);
addPanel.add(btn_add);
}
}
});
});
A:跟swing中一样,用panel来组织页面,其他组件就不需要renderto了
B:取值赋值使用getValue和setValue
3:Ext.panel
完全模拟Swing中的写法
Ext.onReady(function(){
//定义组件
var btn_add = new Ext.Button({
//设置属性
text:"新增"
});
//设置事件
btn_add.on("click",function(){
alert("now is click444=="+Ext.get("userId").getValue());
userId.setValue("updateddd");
}
);
//定义组件
var userId = new Ext.form.TextField({
fieldLabel:"用户编号",
id:"userId"
});
//定义面板
var addPanel = new Ext.Panel({
layout:"form",
width:300,
height:400,
labelWidth:70
});
//把组件放到panel里面
addPanel.add(userId);
addPanel.add(btn_add);
//把panel放到body里面显示出来
addPanel.render(Ext.getBody());
});
A:也可以使用xtype的特性来简化代码,如下:
addPanel.add({xtype:"textfield",fieldLabel:"用户名称"});
B:Ext为了简化代码,使下载量变小,提供了items和buttons,如下:
Ext.onReady(function(){
var addPanel = new Ext.Panel({
layout:"form",
width:300,
height:400,
labelWidth:70,
title:"用户新增界面",
renderTo:Ext.getBody(),
items:[
{
xtype:"textfield",
fieldLabel:"用户编号",
id:"userId"
},
{
xtype:"textfield",
fieldLabel:"用户姓名",
id:"userName"
}
],
buttons:[
{
xtype:"button",
text:"新增",
listeners:{
"click":function(){
alert("now add==="+Ext.get("userId").getValue());
}
}
},
{
xtype:"button",
text:"取消"
}
]
});
});
常见布局
所谓布局就是指容器组件中子元素的分布、排列组合方式。Ext的所有容器组件都支持而局操作,每一个容器都会有一个对应的布局,布局负责管理容器组件中子元素的排列、组合及渲染方式等。
ExtJS的布局基类为https://www.sodocs.net/doc/376585440.html,yout.ContainerLayout,其它布局都是继承该类。
Ext中的一些容器组件都已经指定所使用的布局,比如TabPanel使用card布局、FormPanel 使用form布局,GridPanel中的表格使用column布局等,我们在使用这些组件的时候,不能给这些容器组件再指定另外的布局。常用的布局有border、column、form、card、table等布局。
Form布局
前面已经用了
Column布局
用来实现左右分的,也就是实现一行排多个,如下示例:
Ext.onReady(function(){
var addPanel = new Ext.Panel({
layout:"form",
width:600,
height:400,
labelWidth:70,
title:"用户新增界面",
renderTo:Ext.getBody(),
items:[
{
layout:"column",
items:[
{
columnWidth:.5,
layout:"form",
items:[
{
xtype:"textfield",
fieldLabel:"用户编号",
id:"userId"
},
{
xtype:"textfield",
fieldLabel:"用户姓名",
id:"userName"
}
]
},
{
columnWidth:.5,
layout:"form",
items:[
{
xtype:"textfield",
fieldLabel:"用户年龄",
id:"userAge"
},
{
xtype:"textfield",
fieldLabel:"用户性别",
id:"sex"
}
]
}
]
}
],
buttons:[
{
xtype:"button",
text:"新增",
listeners:{
"click":function(){
alert("now login==="+Ext.get("userId").getValue());
}
}
},
{
xtype:"button",
text:"取消"
}
]
});
});
Border布局
Border布局由类https://www.sodocs.net/doc/376585440.html,yout.BorderLayout定义,布局名称为border。该布局把容器分成东南西北中五个区域,分别由east,south, west,north, center来表示,在往容器中添加子元素的时候,我们只需要指定这些子元素所在的位置,Border布局会自动把子元素放到布局指定的位置。看下面的代码:
Ext.onReady(function(){
new Ext.Viewport({
layout:"border",
items:[
{
region:"north",
height:50,
title:"顶部面板"
},
{
region:"south",
height:50,
title:"底部面板"
},
{
region:"center",
title:"中央面板"
},
{
region:"west",
width:100,
title:"左边面板"
},
{
region:"east",
width:100,
title:"右边面板"
}
]
});
});
Accordion布局(可折叠布局)
Ext.onReady(function(){
new Ext.Panel({
renderTo:"hello",
title:"容器组件",
width:500,
height:200,
layout:"accordion",
layoutConfig: {
animate: true
},
items:[
{
title:"子元素1",
html:"这是子元素1中的内容"
},
{
title:"子元素2",
html:"这是子元素2中的内容"
},
{
title:"子元素3",
html:"这是子元素3中的内容"
}
]
});
});
Card布局
Ext.onReady(function(){
var panel=new Ext.Panel({
renderTo:"hello",
title:"容器组件",
width:500,
height:200,
layout:"card",
activeItem: 0,
layoutConfig: {
animate: true
},
items:[
{
title:"子元素1",
html:"这是子元素1中的内容"
},
{
title:"子元素2",
html:"这是子元素2中的内容"
},
{
title:"子元素3",
html:"这是子元素3中的内容"
}
],
buttons:[
{
text:"切换",handler:changeTab
}
]
});
var i=1;
function changeTab(){
panel.getLayout().setActiveItem(i++);
if(i>2){
i=0;
}
}
});
Table布局
Ext.onReady(function(){
var panel=new Ext.Panel({
renderTo:"hello",
title:"容器组件",
width:500,
height:200,
layout:"table",
layoutConfig: {
columns: 3
},
items:[
{
title:"子元素1",
html:"这是子元素1中的内容",
rowspan:2,
height:100
},
{
title:"子元素2",
html:"这是子元素2中的内容",
colspan:2
},
{
title:"子元素3",
html:"这是子元素3中的内容"
},
{
title:"子元素4",
html:"这是子元素4中的内容"
}
]
});
});
4:Ext.window
Ext.onReady(function(){
var addPanel = new Ext.Window({
layout:"form",
width:600,
height:400,
labelWidth:70,
title:"用户新增界面",
renderTo:Ext.getBody(),
items:[
{
layout:"column",
items:[
{
columnWidth:.5,
layout:"form",
items:[
{
xtype:"textfield",
fieldLabel:"用户编号",
id:"userId"
},
{
xtype:"textfield",
fieldLabel:"用户姓名",
id:"userName"
}
]
},
{
columnWidth:.5,
layout:"form",
items:[
{
xtype:"textfield",
fieldLabel:"用户年龄",
id:"userAge"
},
{
xtype:"textfield",
fieldLabel:"用户性别",
id:"sex"
}
]
}
]
}
],
buttons:[
{
xtype:"button",
text:"新增",
listeners:{
"click":function(){
alert("now login==="+Ext.get("userId").getValue());
}
}
},
{
xtype:"button",
text:"取消"
}
]
});
addPanel.show();
Ext.get("btn_add").on("click",
function(){
if(addPanel.isVisible()){
addPanel.hide();
}else{
addPanel.show();
}
}
);
});
5:Ext.form.DateField
设置xtype:"datefield",
年月日的格式参照文档,比如:format:"Y-m-d",
6:https://www.sodocs.net/doc/376585440.html,boBox
设置xtype:"combo",
要给combobox赋值,需要使用Store,相当于在js里面的一个内存数据库,也就是取值的地方。
xtype:"combo",
fieldLabel:"用户性别",
id:"sex",
mode:"local",
displayField:"sexShow",
valueField:"sexTrue",
store: new Ext.data.ArrayStore({
fields: [
'sexTrue','sexShow'
],
data: [['1','男'], ['2','女']]
})
A:要想后台获取Combobox的真实值,需要设置hiddenName,
B:如果想要不让它自动查询,只要设置triggerAction:?all?
C:可以给combobox设置分页,只需要设置:pageSize:5 ,minListWidth:100,此时的Mode 必须为remote,具体要不要分页,由ext内部决定
D:如果要combox不能输入值,那么就设置readonly为true就可以了
7:Ext.form.FormPanel
对于经常需要跟后台交互的panel可以选用formPanel,它是panel的子类,默认的提交方式是基于ajax的,可以修改成为标准的提交方式:
Ext.onReady(function(){
var addPanel = new Ext.FormPanel({
layout:"form",
width:600,
height:400,
labelWidth:70,
title:"用户新增界面",
renderTo:"myFormDiv",
standardSubmit:true,
method:"post",
url:"a.jsp",
items:[
{
layout:"column",
items:[
{
columnWidth:.5,
layout:"form",
items:[
{
xtype:"textfield",
fieldLabel:"用户编号",
id:"userId",
name:"userId"
},
{
xtype:"textfield",
fieldLabel:"用户姓名",
id:"userName",
name:"userName"
}
]
},
{
columnWidth:.5,
layout:"form",
items:[
{
xtype:"datefield",
format:"Y-m-d",
fieldLabel:"用户年龄",
id:"userAge"
},
{
xtype:"combo",
fieldLabel:"用户性别",
id:"sex",
mode:"local",
valueField:"sexTrue",
displayField:"sexShow",
store: new Ext.data.SimpleStore({
fields: [
'sexTrue','sexShow'
],
data: [['1','男'], ['2','女']]
})
}
]
}
]
}
],
buttons:[
{
xtype:"button",
text:"新增",
listeners:{
"click":function(){
addPanel.getForm().getEl().dom.action=addPanel.url;
addPanel.getForm().submit();
}
}
},
{
xtype:"button",
text:"取消"
}
]
});
});
如果采用默认的ajax提交的方式,可以如下:
addPanel.getForm().submit({
success:function(form,action){
Ext.Msg.alert(‘信息’,action.result.msg);
}
,
failure:function(){
}
});
此时后台如下返回:
<%=”{success:true,msg:’操作成功’}”%>
Ext.grid.GridPanel
先来最简单的:
Ext.onReady(function(){
var cm = new Ext.grid.ColumnModel([