Extjs 开发使用



extjs基础
extjs基础
extjs是什么?
extjs能做什么?
术语
开发环境
界面模板
hello world
Element
UI控件
windows
panel
tabpanel
form
Grid
tree
布局
column layout 列布局
fit Layout
border Layout
accordion Layout
form Layout
table Layout
组件扩展
继承
学习资料
extjs是什么?

ExtJS可以用来开发RIA也即富客户端的AJAX应用,是一个用javascript写 的,主要用于创建前端用户界面,是一个与后台技术无关的前端ajax框架。因此,可以把ExtJS用在.Net、Java、Php等各种开发语言开发的应用中。ExtJs最开始基于YUI技术,由开发人员JackSlocum开发,通过参考JavaSwing等机制来组织可视化组件。该框架完全基于纯Html/CSS+JS技术,提供丰富的跨浏览器UI组件,灵活采用JSON/XML数据源开发。

extjs能做什么?
demo office

术语
一、组件:

1、组件:

所谓组件,就是指可以利用的应用程序组成部件 。EXT最大特点,就是拥有一个庞大、功能齐全、结构及层次分明的组件体系,并在组件的基础上进一步封装出各种实用的控件。我们在开发的时候,只需要直接 使用这些组件及控件 ,就可以创建出丰富多彩的应用程序界面。比如说窗口、树、表格、工具栏、菜等。
2、组件xtype

在Ext中,每一个组件都有一个类定义,比如按钮组件的类是Ext.Button类,空口控件的类是Ext.Window,除了可以通过类名来标识某一个组件以外,Ext还提出了一个xtype的概念,我们可以理解为组件类名的缩写,比如说Ext.tree.TreePanel类对应的类缩写 名称为treepanel。xtypes最大的用途是怎么用于优化组件的创建和渲染过程。 通过指定一个xtype的配置对象的写法,可隐式声明的方式创建组件,使得当不需要立即渲染的情况就只是一个对象,省去不必要的实例化步骤。这时不仅渲染的动作是延时的,而且创建实际对象的这一步也是延时的,从而节省了内存和资源。
3、组件的生存周期

基于组件的每个类,一个周期内各个重要阶段

初始化Initialization

1、配置项对象生效了

The config object is applied.
组件对象的构造器会把全部的配置项传入到其子类中去,并且进行下列所有的步骤。

2、组件的底层事件创建了
The base Component events are created
这些事件由组件对象负责触发。事件有enable, disable, beforeshow, show, beforehide, hide, beforerender, render, beforedestroy, destroy (参阅Component API文档完整的内容)。

3、组件在组件管理器里登记了
The component is registered in ComponentMgr
initComponent这方法总是使用在子类中,就其本身而论,该方法是一个模板方法(template method),用于每个子类去现实任何所需的构造器逻辑(any needed constructor logic)。首先会创建类,然后组件对象各层次里面的每个类都应该调用superclass.initComponent。通过该方法,就可方便地实现(implement),或重写(Override)任意一层构造器的逻辑。

4、状态感知进行初始化(如果有的话)
State is initialized (if applicable)
如果组件是状态感知的,其状态会进行刷新。

5、加载好插件(如果有的话)
Plugins are loaded (if applicable)
如果该组件有指定任何插件,这时便会初始化。

6、渲染好插件(如果必须的话)
The component is rendered (if applicable)
如果指定了组件的renderTo 或 applyTo配置属性,那么渲染工作就会立即开始,否则意味着延时渲染,即等待到显式控制显示,或是其容器告知其显示的命令。


渲染过程 Rendering

1、触发beforerender事件 The beforerender event is fired
这是个可取消的事件,指定的句柄(handler)可阻止组件进行渲染

2、设置好容器 The container is set
如果没有指定一个容器,那么将使用位于DOM元素中组件的父节点作为容器。

3、调用onRender方法 The onRender method is called
这是子类渲染最重要的一个步骤,由于该方法是一个模板方法(template method),用于每个子类去现实任何所需的渲染逻辑(any needed render logic)。首先会创建类,然后组件对象各层次里面的每个类都应调用superclass.onRender。通过该方法,就可方便地实现(implement),或重写(Override)任意一层渲染的逻辑。

4、组件是“隐藏”状态的 The Component is "unhidden"
默认下,许多组件是由CSS样式类如"x-hidden"设置隐藏的。如果 autoShow所配置的值为true,这时就不会有这个"hide"样式类作用在该组件上

5、自定义的类、样式生效了 Custom class and/or style applied
一切组件的子类都支持cls和style 两种特殊的配置属性,分别用于指定用户自定义的CSS样式类和CSS规则。 推荐指定cls的方法来制定组件及其各部分的可视化设置。由于该样式类会套用在组件markup最外的一层元素,所以标准CSS规则会继承到组件下任何子元素的身上。

6、触发render事件 The render event is fired
这是组件通知成功渲染的一个步骤。这时,你可肯定地认为组件的DOM元素是可用的了。如果尝试在渲染之前访问组件,会抛出一个不可用的异常。

7、调用了afterRender方法 The afterRender method is called
这是另外一个实现或重写特定所需的“后渲染”逻辑的模板方法。每个子类应调用superclass.afterRender.

8、组件被隐藏或禁用(如果有的话) The Component is hidden and/or disabled (if applicable)
配置项hidden和disabled到这步生效

9、所有状态感知的事件初始化(如果有的话) Any state-specific events are initialized (if applicable)
状态感知的组件可由事件声明特殊加载和保存状态。如支持,加入此类的事件。

销毁过程 Destruction

1、触发beforedesroy事件 The beforedestroy event is fired
这是个可取消的事件,指定的句柄(handler)可阻止组件被销毁。

2、调用了beforeDestroy方法 The beforeDestroy method is called
这是另外一个实现或重写预定销毁逻辑的模板方法。每个子类应调用superclass.beforeDestroy。

3、元素及其侦听器被移除 Element and its listeners are removed
若组件是渲染好的,所属的元素的事件侦听器和DOM树中的元素都会被移除。

4、调用了onDestroy方法 The onDestroy method is called
这是另外一个实现或重写特定所需的“后销毁”逻辑的模板方法。每个子类应调用superclass.onDestroy。注意 容器类(Container class,和一切容器的子类)提供了一个默认的onDestroy实现,自动遍历其items集合里的每一项,分别地执行子组件身上的destroy方法。

5、在组件管理器中撤销组件对象的登记 Component is unregistered from ComponentMgr
使得不能再从Ext.getCmp获取组件对象

6、触发destroy事件 The destroy event is fired
这是组件成功销毁的一个简单通知。此时组件已经DOM中已是不存在的了

7、组件上的事件侦听器被移除 Event listeners on the Component are removed
组件本身可允许从所属的元素得到事件侦听器。如有的话,连同删除。

二、类

数据支持类(data)

拖X支持类(dd)

布局支持类(layout)

本地状态存储支持类(state)

实用工具类(util)

三、方法

作为类的功能体现,能够产生改变对象本身产生变化的直接因素

四、事件

同类定义的、并且可以在类对象自身状态发生改变的触发。

五、配置选项

用以初始化一个EXTJS类对象的手段

六、属性

能够在程序运行期间被访问,用以了解当前类对象的状态

七、命名空间

能够将编写好的EXTJS类进行有效组织的手段

开发环境
aptana:

firebug:

界面模板
basepage

hello world
Ext.onReady(function(){
alert('Hello world');
})

Element
大多数的JavaScript操作都需要先获取页面上的某个元素的引用,好让你来做些实质性的事情。传统的JavaScript做法,是通过ID获取Dom节点的:

var myDiv = document.getElementById('myDiv');

这样单单返回一个对象(DOM节点),用起来并不是太实用和方便。为了要用那节点干点事情,你还将要手工编写不少的代码;另外,对于不同类型浏览器之间的差异,要处理起来可真头大了。
Element的API是整个Ext库的基础,无论是访问元素(elements)还是完成一些其他动作,都要涉及它。

Ext.onReady(function() {
var myDiv = Ext.get('mydiv');
});

Element包含了常见的DOM方法和属性,提供一个快捷的、统一的、跨浏览器的接口(若使用Element.dom的话,就可以直接访问底层DOM的节点。);
Element.get()方法提供内置缓存(Cache),多次访问同一对象效率上有极大优势;
内置常用的DOM节点的动作,并且是跨浏览器的定位的位置、大小、动画、拖放等等(添加/移除 CSS 类, 添加/移除事件处理程序, 定位, 改变大小, 动画, 拖放)。
myDiv.highlight(); //黄色高亮显示然后渐退
myDiv.addClass('red'); // 添加自定义CSS类 (在ExtStart.css定义)
myDiv.center(); //在视图中将元素居中
myDiv.setOpacity(.25); // 使元素半透明

获取多个DOM节点

想获取多个DOM的节点,难以依靠ID的方式来获取。有可能因为没设置ID,或者你不知道ID,又或者直接用ID方式引用有太多元素了。这种情况下,你就会不用ID来作为获取元素的依据,可能会用属性(attribute)或CSS Classname代替。基于以上的原因,Ext引入了一个异常强大的Dom Selector库,叫做DomQuery。

DomQuery可作为单独的库使用,但常用于Ext,你可以在上下文环境中(Context)获取多个元素,然后通过Element接口调用。令人欣喜的是,Element对象本身便有Element.select的方法来实现查询,即内部调用DomQuery选取元素。

// 每段高亮显示
Ext.select('p').highlight();

DomQuery的选取参数可以是一段较长的数组,其中包括W3C CSS3 Dom选取器、基本XPatch、HTML属性 Ext.DomQuery

响应事件

Ext.onReady(function() {
var paragraphClicked = function(e) {
Ext.get(e.target).highlight();
}
Ext.select('p').on('click', paragraphClicked);
});

e.target是DOM节点,所以我们首先将其转换成为EXT的Elemnet元素,然后执行欲完成的事件,这个例子中,我们看见段落是高亮显示的。

UI控件
windowsWindow 是一种可浮动的、可最小/最大化的、可复原的、可拖动的..等此类的特殊面板。

alert:

Ext.Msg.alert( title , msg , function(btn){} )

title,msg为必选参数,function为可选参数,在关闭弹出窗口后触发。

//widow.alert('hello spoto')!//默认警告框
Ext.Msg.alert('Hello','Hello SPOTO');//ext 警告框

btn:两种值ok,cancel

confirm

参数同confirm

Ext.Msg.confirm('title', 'msg', function(btn){
if (btn == 'ok'){
//处理或者关闭
}
});

btn:三种值(yes,no,cancel)

prompt

Ext.Msg.prompt('Name', 'Please enter your name:', function(btn, text){
if (btn == 'ok'){
//处理text或者关闭
}
});

show

功能很强大,采用config配置形式,比前面的方法使用更方便。

参数很多,在此列举最常用的配置参数:

animEl:对话框弹出和关闭时的动画效果,比如设置为“id1”,则从id1处弹出并产生动画,收缩则相反
buttons:弹出框按钮的设置,主要有以下几种:Ext.Msg.OK, Ext.Msg.OKCANCEL,Ext.Msg.CANCEL, Ext.Msg.YESNO, Ext.Msg.YESNOCANCEL 你也可以自定义按钮上面的字:{"ok","我本来是ok的"}。 若设为false,则不显示任何按钮.
closable:如果为false,则不显示右上角的小叉叉,默认为true。
msg:"消息的内容"
title:"标题"
fn:关闭弹出框后执行的函数
icon:弹出框内容前面的图标,取值为Ext.MessageBox.INFO, Ext.MessageBox.ERROR, Ext.MessageBox.WARNING, Ext.MessageBox.QUESTION
width:弹出框的宽度,不带单位
prompt:设为true,则弹出框带有输入框
multiline:设为true,则弹出框带有多行输入框
progress:设为true,显示进度条,(但是是死的)
progressText:显示在进度条上的字
wait:设为true,动态显示progress
waitConfig:配置参数,以控制显示progress
Ext.MessageBox.show({
title:"标题",
msg:"内容的消息",
buttons:{"ok":"我不再显示OK了"},
fn:function(e){alert(e);},
animEl:"test1",
width:500,
icon:Ext.MessageBox.INFO,
closable:false,
progress:true,
wait:true,
progressText:"进度条"
// prompt:true
// multiline:true
});


进度条的使用

Ext.MessageBox.hide()

Ext.MessageBox.updateProgress(value,"ProgressText","msg")

value为0-1之间的数,表示进度条的进度

Ext.get('btn1').on('click',function(){
Ext.MessageBox.show({
title:"df",
msg:"dfd",
progress:true,
width:300,
closable:true
});
var f=function(v){
return function(){
if(v==12)
{
Ext.MessageBox.hide();
//alert("加载完成!");
}
else
{
var i=v/11;
Ext.MessageBox.updateProgress(i,Math.round(100*i)+"% completed",i);
}
}
}
for(var i=1;i<13;i++)
{
setTimeout(f(i),i*500);//从点击时就开始计时,所以500*i表示每500ms就执行一次
}
})

固定时间控制进度加载

Ext.get("btn1").on(
"click",
function(){
Ext.MessageBox.show({
title:"时间进度条",
msg:"5s后关闭进度框",
progress:true,
width:300,
wait:true,
waitConfig:{interval:600},//0.6s进度条自动加载一定长度
closable:true
});
setTimeout(function(){Ext.MessageBox.hide()},5000);//5后执行关闭窗口函数
}

Ext.Window

var win;
win = new Ext.Window({
applyTo:'hello-win',
layout:'fit',
width:500,
height:300,
closeAction:'hide',
//plain: true,
html:'fsdafsdf',
buttons: [{
text:'Submit',
disabled:true
},{
text: 'Close',
handler: function(){
win.hide();
}
}]
});
win.show();

panel面板Panel是2.0最常用的容器,90%布局任务都离不开面板。布局里的排版元素便是面板,面板如同一张白纸,完全是空白的矩形,没有可视内容。虽然这样,面板也提供了一些预留区域, 方便加入程序所需的UI界面,包括顶部或底部的工具条、菜单栏、头部区域、底部区域和躯干区域。同时内建可展开和可收缩行为的按钮,和其它不同任务预设的按钮。

extjs:

var panel=new Ext.Panel({
title:"面板",
width:500,
height:300
// tbar:[{text:'顶部工具栏'},],
// bbar:[{text:'底部工具栏'}]
}
);
panel.render('panel');

html

<div id="panel"></div>

配置参数:

autoLoad:有效的url字符串,把那个url中的body中的数据加载显示,但是可能没有样式和js控制,只是html数据
autoScroll:设为true则内容溢出的时候产生滚动条,默认为false
autoShow:设为true显示设为"x-hidden"的元素,很有必要,默认为false
bbar:底部条,显示在主体内,//代码:bbar:[{text:'底部工具栏bottomToolbar'}],
tbar:顶部条,显示在主体内,//代码:tbar:[{text:'顶部工具栏topToolbar'}],
buttons:按钮集合,自动添加到footer中(footer参数,显示在主体外)//代码:buttons:[{text:"按钮位于footer"}]
buttonAlign:footer中按钮的位置,枚举值为:"left","right","center",默认为right
collapsible:设为true,显示右上角的收缩按钮,默认为false
draggable:true则可拖动,但需要你提供操作过程,默认为false
html:主体的内容
id:id值,通过id可以找到这个组件,建议一般加上这个id值
width:宽度
height:高度
title:标题
titleCollapse:设为true,则点击标题栏的任何地方都能收缩,默认为false.
applyTo:(id)呈现在哪个html元素里面
contentEl:(id)呈现在哪个html元素里面,把el内的内容呈现
renderTo:(id)呈现在哪个html元素里面
渲染:

applyTo是将组件加在了指定元素之后,而renderTo则是加在指定元素之内。

applyTo与renderTo区别

//applyTo将组件 渲染到某一个节点的父节点
var applyTo=new Ext.Panel({title:'面板_applyTo',width:300,height:300,applyTo:'applyTo'});
//指定el参数,然后直接调用render方法来渲染组件
var el=new Ext.Panel({title:'面板_el',width:300,height:300,el:'el'})
el.render();
//renderTo渲染到页面中的某一个节点
var renderTo=new Ext.Panel({title:'面板_renderTo',width:300,height:300,renderTo:'renderTo'})
alert(renderTo.el.dom.innerHTML);

tabpanelvar tabs = new Ext.TabPanel({
renderTo: document.body,
width:450,
height:300,
activeTab: 0,//0 是指,默认显示(访问)的是哪一个子面板。0是第一次,如果不指定该属性,默认不显示子面板内容,只有当用户点击子面板后才显示。
defaults:{autoHeight: true},//默认自适应高度
items:[
{contentEl:'script', title: 'Short Text'},
{contentEl:'markup', title: 'Long Text',disabled:true},
{autoLoad: {url: 'data/ajax.html', params: 'foo=bar&wtf=1'},
title: 'ajax',
listeners: {activate: function(){alert('f')}}
}
]
});

items 属性,表示子面板组。内容可以用html 元素ID 。比如:

items:[
{contentEl:'script', title: 'Short Text'},
{contentEl:'markup', title: 'Long Text'}
]

这样这两个子面板的内容将是ID为sript 和markup 的元素内容。

也可以,以html属性直接表示子面板的内容:

items:[
{html:'script', title: 'Short Text'},
{html:'markup', title: 'Long Text'}
]

autoLoad: {url: 'data/ajax.html', params: 'foo=bar&wtf=1'}

指切换到这个页面,内容显示为动态加载的,比如这里用了一个ajax方式,url 发送目标,params是参数形式。

listeners: {activate: handleActivate}

当面板切换到这个页面将触发事件:handleActivate

disabled:true

指这个页面不能点击

formExtjs对普通的html form进行了一些封装,使其具有基本的外观和一些简便的和服务器进行通信的方法。Extjs中的表单组件是Ext.form.BasicForm,不过最简单最常用的是Ext.form.FormPanel控件,它继承自Panel,具有一定的界面显示控制能力,它其中包含着一个BasicForm对象,用来执行向服务器提交,加载等动作。Extjs也对常用的html表单项进行了封装,提供了一些额外的功能,比如数据验证。实际使用的时候只要向 FormPanel中添加这些表单项即可。常见的表单项有,TextField,NumberField,Radio,CheckBox等。
var top = new Ext.FormPanel({
labelAlign: 'top',//label对齐方式
frame:true,//圆角显示
title: 'Multi Column, Nested Layouts and Anchoring',//标题
bodyStyle:'padding:5px 5px 0',//样式
width: 600,
items: [{//表单元素
layout:'column',
items:[{
columnWidth:.5,//50%
layout: 'form',//布局方式
items: [{
xtype:'textfield',//文本框
fieldLabel: 'First Name',
name: 'first',
anchor:'95%'//宽度=容器宽度的50%" (-10, -250',"宽度=容器宽度-10,高度=容器宽度-250")
}, {
xtype:'textfield',
fieldLabel: 'Company',
name: 'company',
anchor:'95%'
}]
},{
columnWidth:.5,
layout: 'form',
items: [{
xtype:'textfield',
fieldLabel: 'Last Name',
name: 'last',
anchor:'95%'
},{
xtype:'textfield',
fieldLabel: 'Email',
name: 'email',
vtype:'email',
anchor:'95%'
}]
}]
},{
xtype:'htmleditor',//编辑器
id:'bio',
fieldLabel:'Biography',
height:200,
anchor:'98%'
}],

buttons: [{
text: 'Save',
handler : function() {
var formpanel1 =top;
if (formpanel1.form.isValid()) {
this.disabled = true;
formpanel1.getForm().submit({
url : 'save.action',//提交给后台。后台相应save方法。此处成功调用了该方法
method : 'post',
waitTitle : '请稍等……',
waitMsg : '正在上传数据……',
success : function() {
Ext.Msg.alert("成功", "操作成功!");
this.disabled = false;
},
failure : function() {
Ext.Msg.alert("出错啦", "数据保存失败!");
this.disabled = false;
}
});
}
}
},{
text: 'Cancel'
}]
});
top.render(document.body);

GridGrid控件和其它可以显示 数据的控件,能够支持多种数据类型,如二 维数组、Json数据和XML数据,甚至包括我们 自定义的数据类型。Ext为我们提供了一个桥梁 Ext.data.Store,通过它我们可以把任何 格式的数据转化成grid可以使用的形式,这样就不需要为每种数据格式写一个grid的实现了。

Ext.onReady(function() {

// 定义一个ColumnModel,表头中有四列
var cm = new Ext.grid.ColumnModel([
{header: ' 编号 ' ,dataIndex: ' id ' },
{header: ' 性 别 ' ,dataIndex: ' sex ' },
{header: ' 名 称 ' ,dataIndex: ' name ' },
{header: ' 描 述 ' ,dataIndex: ' descn ' }
]);

cm.defaultSortable = true;

该ColumnModel定义了表格的四个列,其每列的名称和对应的数据键。请注意defaultSortable属性,即为每个列都安上一个可以排序的功能。如果只想某些列举有该功能,可以设置:

header:'编号',dataIndex:'id',Sortable:true

Ext.data.Store

//二维数组:
// ArrayData
var data = [
[ ' 1 ' , ' male ' , ' name1 ' , ' descn1 ' ],
[ ' 2 ' , ' male ' , ' name1 ' , ' descn2 ' ],
[ ' 3 ' , ' male ' , ' name3 ' , ' descn3 ' ],
[ ' 4 ' , ' male ' , ' name4 ' , ' descn4 ' ],
[ ' 5 ' , ' male ' , ' name5 ' , ' descn5 ' ]
];

// ArrayReader
var ds = new Ext.data.Store({
proxy: new Ext.data.MemoryProxy (data),
reader: new Ext.data.ArrayReader ({}, [
{name: ' id ' },
{name: ' sex ' },
{name: ' name ' },
{name: ' descn ' }
])
});
ds.load();

ds要对应两个部分:proxy和reader。proxy告诉我们从哪里获得数据,reader告诉我们如何解析这个数据。

现在用的是Ext.data.MemoryProxy,它将内存中的数据data作为参数传递。Ext.data.ArrayReader专门用来解析数 组,并且告诉我们它会按照定义的规范进行解析,每行按顺序读取四个数据,第一个叫id,第二个叫sex,第三个叫name,第四个descn。这些是跟 cm定义中的dataIndex对应的。这样cm就知道哪列应该显示那条数据了。

记得要执行一次ds.load(),对数据进行初始化。

数据显示:

var grid = new Ext.grid.GridPanel({
title:'数据列表',
height:200,
width:500,
ds: ds,
cm: cm
});
grid.render(document.body);
});

*表格中添加CheckBox*

var sm = new Ext.grid.CheckboxSelectionModel();
var cm = new Ext.grid.ColumnModel([
new Ext.grid.RowNumberer(),//自动行号
sm,//添加的地方
{header:'编号',dataIndex:'id'},
{header:'性别',dataIndex:'sex'},
{header:'名称',dataIndex:'name'},
{header:'描述',dataIndex:'descn'}
]);

var grid = new Ext.grid.GridPanel({
el: 'grid3',
ds: ds,
cm: cm,
sm: sm,//添加的地方
title: 'HelloWorld'
});

在Grid上触发事件

grid.addListener('cellclick', cellclick);
function cellclick(grid, rowIndex, columnIndex, e) {
var record = grid.getStore().getAt(rowIndex); //Get the Record
var fieldName = grid.getColumnModel().getDataIndex(columnIndex); //Get field name
var data = record.get(fieldName);
Ext.MessageBox.alert('show','当前选中的数据是'+data);
}

Grid中右击快捷菜单

grid.addListener('rowcontextmenu', rightClickFn);//右键菜单代码关键部分
var rightClick = new Ext.menu.Menu({
id:'rightClickCont',
items: [
{
id: 'rMenu1',
handler: rMenu1Fn,//点击后触发的事件
text: '右键菜单1'
},
{
//id: 'rMenu2',
//handler: rMenu2Fn,
text: '右键菜单2'
}
]
});
function rightClickFn(grid,rowindex,e){
e.preventDefault();//阻止默认行为,如:阻止脚本运行或者阻止事件处理函数的执行
rightClick.showAt(e.getXY());//显示位置
}
function rMenu1Fn(){
Ext.MessageBox.alert('right','rightClick');
}


将一列中的数据根据要求进行格式化

比如说性别字段根据其male或female改变显示的颜色,这种ColumnMode中设计:

var cm = new Ext.grid.ColumnModel([
new Ext.grid.RowNumberer(),
sm,
{header:'编号',dataIndex:'id'},
{header:'性别',dataIndex:'sex',renderer:changeSex},
{header:'名称',dataIndex:'name'},
{header:'描述',dataIndex:'descn'}
]);
cm.defaultSortable = true;

function changeSex(value){
if (value == 'male') {
return "<span style='color:red;font-weight:bold;'>红男</span>";
} else {
return "<span style='color:green;font-weight:bold;'>绿女</span>";
}
}

Json数据

var data = {
'coders': [
{ 'id': '1', 'sex': 'male', 'name':'McLaughlin', 'descn': 'brett@newInstance.com' },
{ 'id': '2', 'sex': 'male','name':'Hunter', 'descn': 'jason@servlets.com' },
{ 'id': '3', 'sex': 'female','name':'Harold', 'descn': 'elharo@macfaq.com' },
{ 'id': '4', 'sex': 'male','name':'Harolds', 'descn': 'elhaross@macfaq.com' }
],
'musicians': [
{ 'id': '1', 'name': 'Clapton', 'descn': 'guitar' },
{ 'id': '2', 'name': 'Rachmaninoff', 'descn': 'piano' }
]
}
//ds使用的MemoryProxy对象和JsonReader对象
var ds = new Ext.data.Store({
proxy: new Ext.data.MemoryProxy(data),
reader: new Ext.data.JsonReader({root: 'coders'}, [
{name: 'id'},
{name: 'sex'},
{name: 'name'},
{name: 'descn'}
])
});

ds.load();

var grid = new Ext.grid.GridPanel({
el: 'grid3',
ds: ds,
cm: cm,
sm: sm,
title: 'HelloWorld',
autoHeight: true//一定要写,否则显示的数据会少一行
});
grid.render();

从服务器获取数据和数据翻页控件

服务端返回数据(参数:start和limit):

{totalProperty:100,root:[{'id':'0','name':'name0','descn':'descn0'},{'id':'1','name':'name1','descn':'descn1'},{'id':'2','name':'name2','descn':'descn2'},{'id':'3','name':'name3','descn':'descn3'},{'id':'4','name':'name4','descn':'descn4'},{'id':'5','name':'name5','descn':'descn5'},{'id':'6','name':'name6','descn':'descn6'},{'id':'7','name':'name7','descn':'descn7'},{'id':'8','name':'name8','descn':'descn8'},{'id':'9','name':'name9','descn':'descn9'}]}

我们使用分页控件来控制Grid的数据:

var sm = new Ext.grid.CheckboxSelectionModel();

var cm = new Ext.grid.ColumnModel([
new Ext.grid.RowNumberer(),
sm,
{header:'编号',dataIndex:'id'},
{header:'性别',dataIndex:'sex'},
{header:'名称',dataIndex:'name'},
{header:'描述',dataIndex:'descn'}
]);
cm.defaultSortable = true;

var ds = new Ext.data.Store({
proxy: new Ext.data.HttpProxy({url:'data.asp'}),
reader: new Ext.data.JsonReader({
totalProperty: 'totalProperty',
root: 'root'
}, [
{name: 'id'},
{name: 'name'},
{name: 'descn'}
])
});
ds.load({params:{start:0,limit:10}});

var grid = new Ext.grid.GridPanel({
el: 'grid3',
ds: ds,
cm: cm,
sm: sm,
title: 'ASP->JSON',
bbar: new Ext.PagingToolbar({
pageSize: 10,
store: ds,
displayInfo: true,
displayMsg: '显示第 {0} 条到 {1} 条记录,一共 {2} 条',
emptyMsg: "没有记录"
}),
tbar: new Ext.PagingToolbar({
pageSize: 10,
store: ds,
displayInfo: true,
displayMsg: '显示第 {0} 条到 {1} 条记录,一共 {2} 条',
emptyMsg: "没有记录"
})
});
grid.render();
})

在Grid的上方添加按钮

var grid = new Ext.grid.GridPanel({
el: 'grid3',
ds: ds,
cm: cm,
sm: sm,
title: 'HelloWorld',
tbar: new Ext.Toolbar({
items:[
{
id:'buttonA'
,text:"Button A"
,handler: function(){ alert("You clicked Button A"); }
}
,
new Ext.Toolbar.SplitButton({})
,{
id:'buttonB'
,text:"Button B"
,handler: function(){ alert("You clicked Button B"); }
}
,
'-'
,{
id:'buttonc'
,text:"Button c"
}
]
})
});

tree// shorthand
var Tree = Ext.tree;
var tree = new Tree.TreePanel({
autoScroll: true,
animate: true,
enableDD: true,
containerScroll: true,
width:300,
//border: false,
// auto create TreeLoader
dataUrl: 'data/json.php',
root: {
nodeType: 'async',
text: 'Ext JS',
draggable: false,
id: 'src'
}
});
// render the tree
tree.render(document.body);
tree.getRootNode().expand();

Ext.tree.TreeLoader:

[{
id: 1,
text: 'A leaf Node',
leaf: true
},{
id: 2,
text: 'A folder Node',
children: [{
id: 3,
text: 'A child Node',
leaf: true
}]
}]

tree_php_mysql

布局
column layout 列布局在子元素中指定使用columnWidth或width来指定子元素所占的列宽度。 columnWidth表示使用百分比的形式指定列宽度。 width则是使用绝对象素的方式指定列宽度,在实际应用中可以混合使用两种方式。
new Ext.Panel({
renderTo:document.body,
width:600,
height:300,
layout:'column',
items:[{
columnWidth:.5,
title:'面板1'
},{
columnWidth:.5,
title:'面板2'
}]
})

fit LayoutFit布局,子元素将自动填满整个父容器(对元素设置宽度无效),如果容器组件中有多个子元素,则只会显示第一个子元素。

var win = new Ext.Window({
title: "Hello World",
renderTo: document.body,
width: 400,
height: 250,
x: 150,
y: 50,
layout: "fit",
items: [
{xtype:"panel", title:"O"},
{xtype:"panel", title:"K"}
]
});

win.show();


border LayoutBorder布局由类Ext.layout.BorderLayout定义,布局名称为border。该布局把容器分成东南西北中五个区域,分别由east,south, west,north, cente来表示,在往容器中添加子元素的时候,我们只需要指定这些子元素所在的位置,Border布局会自动把子元素放到布局指定的位置。 Viewport用于做整体布局 视见区Viewport是以document.body作容器的实用类,它会与浏览器视图自适应尺寸,是全屏幕应用的基础,如浏览器大小调节、布局重新计算的问题由该类自动完成。 注意视见区Viewport除了document.body元素外不能渲染在其它的容器上,所以一个页面只能有一个视见区。
new Ext.Viewport({
layout:"border",
items:[
{
region:"north",
height:80,
xtype: "label",
//style: "border: 1px solid red;padding:1px;",
frame: true,
text: "cdred.net study club"
},
{
region:"south",
height:20,
xtype:'label',
text:'Status show zone..'
},
{
region:"center",
title:"中央面板"
},
{
region:"west",
width:200,
title:"系统栏目",
collapsible: true
},
{
region:"east",
width:150,
collapsed: true,
collapsible: true,
title:"在线好友"
}

]

});

accordion LayoutAccordion布局由类Ext.layout.Accordion定义,表示可折叠的布局,点击每一个子元素的头部名称或右边的按钮,则会展开该面板,并收缩其它已经展开的面板。
注意如果你是用 panel之类的 必须拥有 title:'' 属性

new Ext.Panel({
renderTo:document.body,
title:'容器',
width:500,
height:300,
layout:'accordion',
layoutConfig:{
animate:true//启动动画效果
},
items:[
{title:'子元素1',html:'这是子元素1'},
{title:'子元素2',html:'这是子元素2'},
{title:'子元素3',html:'这是子元素3'}
]
})

form LayoutForm布局由类Ext.layout.FormLayout定义,名称为form,是一种专门用于管理表单中输入字段的布局,这种布局主要用于在程序中创建表单字段或表单元素等使用。
Ext.form.FormPanel这个类默认布局使用的是Form布局,因此我们直接使用FormPanel即可。

var panel = new Ext.Panel({
layout:"form",
title: "form",
renderTo:document.body,
width: 400,
height:250,
frame: true,
hideLabel: true,
collapsible: true,//控制收缩
labelAlign:right,
bodyStyle: "padding:20px;",
defaultType:"textfield",
items:[
{fieldLabel:"Hello"},
{fieldLabel:"World"}
]
});

table LayoutTable布局由类Ext.layout.TableLayout定义,类以于html中的table,可以对行或列进行合并。
var panel = new Ext.Panel({
title: "Hello World",
renderTo:document.body,
layout: "table",
width: 500,
height: 300,
bodyStyle:'padding:20px;',
layoutConfig: {
columns: 3
},
items: [
{xtype:"panel", title:"hello", html:"hello context", rowspan:2,height:95},
{xtype:"panel", title:"world", html:"world context", colspan:2},
{xtype:"panel", title:"fu", html:"cheng context"},
{xtype:"panel", title:"zhou", html:"du context"}
]
});

组件扩展
有时候你打算生成一个带有若干配置项(config options)的组件(component),这些配置项你会想是让它可复的。就好像一种情况,有一部分的面板是已经固定好高、宽的,其中只有标题是不同的,我们可以把它做成预配置类(preconfigured class)。
使用构造器函数

构造器函数是完成该任务的方法之一,如下例:

// 构造器函数
var MyPanel = function(config) {
Ext.apply(this, {
// 在这里设定预配置的参数项

width: 300,
height: 300
});
MyPanel.superclass.constructor.apply(this, arguments);
};
// My Panel继承了Ext.Panel
Ext.extend(MyPanel, Ext.Panel, {});

var myfirstpanel = new MyPanel({
title: 'My First Panel'
});

var mysecondpanel = new MyPanel({
title: 'My Second Panel'
});

工厂模式

生成“预配置对象”的一种途径是使用工厂模式(Factong Design Pattern)。透过工厂函数返回一个全新的实例(该函数包含了预先配置好的参数项),工厂模式的方法不需要类的继承。 如果纯粹为了制定固定的配置项参数来讲工厂模式是一个不错的方法,其内部原理比继承、覆盖某个类来得简单。
function createMyPanel(config) {
return new Ext.Panel(Ext.apply({//在这里设定预配置的参数项
width: 300,
height: 300
}, config));
};

var myfirstpanel = createMyPanel({
title: 'My First Panel'
});

var mysecondpanel = createMyPanel({
title: 'My Second Panel'
});


扩展功能

使用OO的类的其中一个原因是你打算从另外一个类的基础上扩展新的功能,假设现在有一面板类,我们在此基础上增加一个新的方法并重写(override)父类的一个方法,过程如下:

// Constructor
var MyPanel = function(config) {
//这里复用配置项
Ext.apply(this,
width: 300,
height: 300
});
// 调用父类的构造函数,提取父类的功能
MyPanel.superclass.constructor.apply(this, arguments);
// 在这里你可以为当前对象新添加功能
// 如事件:
this.on('click', function() {alert("You Clicked " + this.title);}, this);
};
// My Panel继承了Ext.Panel
Ext.extend(MyPanel, Ext.Panel, {
// 在这里你可以为当前的类加入静态的变量,所有这个类生成的实例都是使用这里声明的变量
// 如果你不确定请在构造器内设定。不要在这里放置由'new'或'xtype'操作而成的对象。在构造器内设定配置项对象会更安全。

// 新添加的函数
myNewFunction: function() {
},
// 重写原有函数
onRender: function() {
MyPanel.superclass.onRender.apply(this, arguments);
this.myNewFunction();
}
});

var myfirstpanel = new MyPanel({
title: 'My First Panel'
});

var mysecondpanel = new MyPanel({
title: 'My Second Panel'
});


另一种方法是用构造器的方式写出代码:

var MyPanel = function(config) {
// 调用父类的构造函数,提取父类的功能
MyPanel.superclass.constructor.call(this, Ext.apply({
//这里复用配置项
width: 300,
height: 300
}, config));

// 位于构造器之后,在这里你可以为当前对象新添加功能(如处理如事件)
this.on('click', function() {alert("你已点击" + this.title);}, this);
};


以上的方法是重写构造器的方式实现继承的,另外我们还可以重写initComponents方法写出相同的功能,但需要指出是initComponent方法是属于 Ext.Components的方法,只能在组件上使用,不是一个通用的方法。这里是一个示例:

var MyPanel = Ext.extend(Ext.Panel, {
// 在这里你可以为当前的类加入静态的变量,所有这个类生成的实例都是使用这里声明的变量
// 如果你不确定请在构造器内设定。不要在这里放置由'new'或'xtype'操作而成的对象。在构造器内设定配置项对象会更安全。

initComponent: function() {
//Reusable config options here
Ext.apply(this,
width: 300,
height: 300
});
// 调用父类的构造函数,提取父类的功能
MyPanel.superclass.initComponent.apply(this, arguments);
// 位于构造器之后,在这里你可以为当前对象新添加功能(如处理如事件)
this.on(
'click',
function() {
alert("你已点击" + this.title);
},
this
);
},
// 新添加的函数
myNewFunction: function() {
},
// 重写原有函数
onRender: function() {
MyPanel.superclass.onRender.apply(this, arguments);
this.myNewFunction();
}
});


你首先可能会观察到的是这儿没有构造函数。Ext会为你创建构造函数。这个构造函数有点不同,叫initComponent。

这在高级教程和例子常见的使用方法。只要简单记住它做的事情与构造函数是差不多的。

推荐在调用父类的构造器或initComponent方法之后,为当前对象新添加事件。

MyPanel.superclass.constructor.apply(this, arguments);
// 位于构造器之后,在这里你可以为当前对象新添加功能(如处理如事件)
this.on(
'click',
function() {
alert("你已点击" + this.title);
},
this
);


工厂模式的案例中你可以在工厂方法以外的地方登记事件的处理函数。

myFirstPanel.on(
'click',
function() {
alert("你已点击" + this.title);
},
myFirstPanel //作用域
);


另外,除了添加listeners配置项还有其他处理监听器的方法,不过我推荐高级用户使用。

完成同一件事在Ext中有不同的方式。挑选一种你较倾向的方法。

Extending_ext_components

继承
Ext提供了这样的一个实用函数 Ext.extend (API 参考) 在EXT框架中实现类继承的机制。这赋予了你扩展任何JavaScript基类的能力,而无须对类自身进行代码的修改(这里通常指的是子类,或是从它继承的,一个基类)扩展Ext组件这是个较理想的方法。

要从一个现有的类创建出一个新类,首先要通过一个函数声明新类的构造器,然后调用新类属性所共享的扩展方法。这些共享的属性通常是方法,但是如果要在实例之间共享数据(例如,Java中的静态类变量),应该也一同声明。

JavsScript并没有提供一个自动的调用父类构造器的机制,所以你必须通过属性superclass在你的构造器中显式调用父类。第一个参数总是this,以保证构造器工作在调用函数的作用域。

MyNewClass = function(arg1, arg2, etc) {
// 显式调用父类的构造函数
MyNewClass.superclass.constructor.call(this, arg1, arg2, etc);
};

Ext.extend(MyNewClass, SomeBaseClass, {
theDocument: Ext.get(document),
myNewFn1: function() {
// etc.
},
myNewFn2: function() {
// etc.
}
});

下面的一个例子是Ext的实际案例,用于可缩放,拖动元素,X、Y的坐标值指定了对象可在垂直、水平方向拖动的距离。

// 创建新类的构造函数
Ext.ResizableConstrained = function(el, config){
Ext.ResizableConstrained.superclass.constructor.call(this, el, config);
};

// 扩展基类
setXConstraint()和setYConstraint来限制拖拽范围
Ext.extend(Ext.ResizableConstrained, Ext.Resizable, {
setXConstraint : function(left, right){
// 得到父类的属性dd和setXConstraint的引用
this.dd.setXConstraint(left, right);
},

setYConstraint : function(up, down){
// 得到父类的属性dd和setYConstraint的引用
this.dd.setYConstraint(up, down);
}
});

// 创建新类的实例
var myResizable = new Ext.ResizableConstrained('resize-el', {
width: 200,
height: 75,
minWidth:100,
minHeight:50,
maxHeight:150,
draggable:true
});

//调用新方法
myResizable.setYConstraint(0,300);
myResizable.setXConstraint(0,300);


Ext.Component

大多数Ext窗口小部件(如Form elements, Panels, Toolbars, ..)继承自Ext.Component(那些没有继承的将在Ext3中实现继承)。

预配置类

最简单的扩展Ext.Component的方式(或者任何继承自它的类)就是延续Ext1.X中利用Ext.extend()的做法。然而还有个差别,就是你不需要定义自己的构造函数(构造函数将由initComponent()来处理,文章后面将会讲到)。如果你所需的是定义一些自己的缺省类来重用(指的是这里和ExtJS社区作为预配置类),所有你所需要做的就是:

//定义组件Ext.some.component的预配置类MyComponent
MyComponent = Ext.extend(Ext.some.component, {
myDefault1: '..',
myDefault2: '..'
});

//注册成xtype以便延迟加载
Ext.reg('mycomponentxtype', MyComponent);

在以上示例中,Ext.extend()中的第二个参数对象包含的自定义参数可覆盖Ext.some.component中已经支持的缺省参数。

以上示例看上去较简单,但能够让你从程序中重构除去相当数量重复的代码,并生成可重用的对象。举个例子,你可以用预配置选项创建一个Ext.some.component的实例,代码如下:

var myComponent = new MyComponent();

或者通过你注册过的Component XType延迟加载,下面示例作为Panel的组件项:

{..
items: [ {xtype: 'mycomponentxtype'} ]
..}

扩展Ext.Component

好的,虽然预配置类很有用,但是目前为止我们还没有添加任何其他的功能给继承类。我们需要覆盖一些方法来实现。这是Ext2.X精彩的地方。

Ext.Component源自1.x,但是在2.x中,它得到了扩展和加强,使它成为了整个架构中最基础的类。现在组件提供统一的组件创建、渲染、事件处理、状态维护、销毁模型,而且Ext中的每个组件,凡是需要这些特性的现在都扩展自Component。

一个可重用模板

MyComponent = Ext.extend(Ext.some.component, {
//缺省构造参数,可被自定义设置覆盖
propA: 1,

initComponent: function(){
//在组件初始化期间调用的代码

//因为配置对象应用到了“this”,所以属性可以在这里被覆盖,或者添加新的属性
//(如items,tools,buttons)
Ext.apply(this, {
propA: 3
});

//调用父类代码之前

//调用父类构造函数(必须)
MyComponent.superclass.initComponent.apply(this, arguments);

//调用父类代码之后
//如:设置事件处理和渲染组件
},

//覆盖其他父类方法
onRender: function(){

//调用父类代码之前

//调用父类相应方法(必须)
MyScope.superclass.onRender.apply(this, arguments);

//调用父类代码之后

}
});

//注册成xtype以便能够延迟加载
Ext.reg('mycomponentxtype', MyComponent);


var myComponent = new MyComponent({
propA: 2
});
//或者延迟加载:
{..
items: {xtype: 'mycomponentxtype', propA: 2}
..}


学习资料
desktop

官方网站:http://www.extjs.com/

index This page is generated by 1625
2010-09-09 19:54:11
相关资源:EXTjs图开编程EXTJS
已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页