ExtJS 4 组件详解
2014-12-25 22:39
225 查看
ExtJS4的应用界面是由很多小部件组合而成的,这些小部件被称作“组件(
子组件通过容器的
容器通过“布局管理器(ExtJS4布局和容器》
APIDocsforComponent中有列出。上面那个例子说明了如何添加已经初始化的组件到一个容器中。在大的应用中,这种方式是不可行的,因为这种方法需要每个组件都是初始化过的,但是大的应用中,由于使用的方式有些组件可能根本没有被用到(比如有100个页面的应用,一个用户登录进来只操作了两个页面,这时把其他98个页面的组件全部初始化是不合理的),例如一个用到
下面的示例代码通过
运行一下代码,第一个tab的渲染对话框马上就弹出了,因为默认激活第一个tab,所以它的父容器
不点击第二个tab,它的对话跨就一直不会弹出,这说明tab不会被渲染直到被用到,tab的
上面的代码实例化了一个
有几个属性是使用浮动组件时值得注意的:
当创建一个新的UI类时,必须决定这个类是引用其他组件的实例还是扩展这个组件。
推荐扩展最接近的组件添加自己需要的功能,这是因为使用继承的方式可以自动获得组件原有的自动生命周期管理能力,包括按须渲染、布局管理器提供的尺寸位置管理、从容器中删除的自动析构等。
扩展一个原有组件会让扩展出的组件隶属于组件层级中,这样比一个外部类引用并掌管ExtJS组件的实例要容易的多。
Subclassing子类化
ExtJS的类系统使得扩展一个现有组件变的很简单。接下来的代码演示了创建一个
TemplateMethods模板方法
ExtJS使用了模板方法模式把特殊行为委托给子类。
这意味着每一个继承链上的类都可以“贡献”一段包含特定逻辑的片段到组件的生命周期中。每一个类实现自己特殊行为的同时,还允许其他在继承链上的类继续贡献它们自己的逻辑。
一个例子就是
下图指示了
这有一个实现
需要注意的是很多模板方法都有一个对应的事件。例如组件
下面列举的是
WhichClassToExtend扩展那个类
选择最合适的类继承是个影响效率的问题,基类能提供的功能也是个问题。现在有种倾向是无论什么样的UI组件都从
Panel类有很多能力:
Border
Header
Headertools
Footer
Footerbuttons
Toptoolbar
Bottomtoolbar
ContainingandmanagingchildComponents
如果不需要这些功能,继承
Component组件
如果创建的UI组件不需要包含任何其他组件,就比如只是对HTML片段的封装就可以满足需求的组件,推荐扩展
用法:
这个例子仅作为例子,
Container容器
如果UI组件需要包含其他组件的能力,但是又不需要
Panel面板
如果需求的UI组件必须有header,footer或者toolbar,
注意
从
Component)”,所有组件都是
Ext.Component的子类,
Ext.Component提供了生命周期管理包括初始化、渲染、大小和尺寸管理、销毁等功能,这使得所有
Ext.Component的子类都自动分享了这些能力。ExtJS提供了各式各样丰富的组件,每一个组件都很容易被扩展创建成自定义组件。
TheComponentHierarchy组件层级
容器(Container)是个可以容纳其他组件的特殊组件。通常的应用都是由很多嵌套的组件构成,这些组件有一个类似树状的结构,这就是组件的层级。容器负责管理子组件的生命周期包括始化、渲染、大小和尺寸管理、销毁。通常的应用最顶层的组件都是
Viewport然后有其他容器或者组件嵌套在其中:
子组件通过容器的
items加入到容器中,下面这个例子通过
Ext.create方法创建了两个
Panel,并把它们当作子组件添加到
Viewport中:
varchildPanel1=Ext.create('Ext.panel.Panel',{
title:'ChildPanel1',
html:'APanel'
});
varchildPanel2=Ext.create('Ext.panel.Panel',{
title:'ChildPanel2',
html:'AnotherPanel'
});
Ext.create('Ext.container.Viewport',{
items:[childPanel1,childPanel2]
});
容器通过“布局管理器(
LayoutManager)”管理子组件的尺寸和位置。关于布局和容器的详细内容可以查看《
XTypesandLazyInstantiationxtype和延迟加载
每个组件都有一个代称叫做xtype,例如
Ext.panel.Panel的
xtype是
panel。所有组件的
xtype在
TabPanel的应用,
TabPanel的每个tab只当用户点击它的时候再渲染即可。这就是引入
xtype机制的原因,有了
xtype可以让一个容器的子组件事先定义好,到真正需要的时候再初始化。
下面的示例代码通过
TabPanel展示了延迟加载和延迟渲染,每个tab都有个响应函数监听tab的渲染
render事件,渲染的时候会弹出一个对话框告知当前tab已经渲染
Ext.create('Ext.tab.Panel',{
renderTo:Ext.getBody(),
height:100,
width:200,
items:[
{
//ExplicitlydefinethextypeofthisComponentconfiguration.
//ThistellstheContainer(thetabpanelinthiscase)
//toinstantiateaExt.panel.Panelwhenitdeemsnecessary
xtype:'panel',
title:'TabOne',
html:'Thefirsttab',
listeners:{
render:function(){
Ext.MessageBox.alert('RenderedOne','TabOnewasrendered.');
}
}
},
{
//thiscomponentconfigurationdoesnothaveanxtypesince'panel'isthedefault
//xtypeforallComponentconfigurationsinaContainer
title:'TabTwo',
html:'Thesecondtab',
listeners:{
render:function(){
Ext.MessageBox.alert('RenderedOne','TabTwowasrendered.');
}
}
}
]
});
运行一下代码,第一个tab的渲染对话框马上就弹出了,因为默认激活第一个tab,所以它的父容器
TabPanel立即初始化和渲染了它
不点击第二个tab,它的对话跨就一直不会弹出,这说明tab不会被渲染直到被用到,tab的
render事件不会触发直到tab被激活
ShowingandHiding显示和隐藏
所有组件都有内置的show和
hide方法。默认的css样式应用的是
display:none,可以通过
hideMode改变
varpanel=Ext.create('Ext.panel.Panel',{
renderTo:Ext.getBody(),
title:'Test',
html:'TestPanel',
hideMode:'visibility'//usetheCSSvisibilitypropertytoshowandhidethiscomponent
});
panel.hide();//hidethecomponent
panel.show();//showthecomponent
FloatingComponents浮动组件
浮动组件定位于文档流之外,使用的是CSS的绝对定位属性,不受父容器的布局控制。有些组件,例如Window,默认就是浮动的,任何组件都可以通过
floating属性配置成浮动的。
varpanel=Ext.create('Ext.panel.Panel',{
width:200,
height:100,
floating:true,//makethispanelanabsolutely-positionedfloatingcomponent
title:'Test',
html:'TestPanel'
});
上面的代码实例化了一个
Panel对象,但是并没有渲染它。通常一个组件要么有
renderTo属性配置渲染到什么位置,要么就作为容器的一个子组件由容器负责渲染,但是这个例子的浮动组件即不需要
renderTo也不需要作为子组件。浮动组件第一次调用
show方法时,会被自动渲染到DOM的document.body中:
1
panel.show();//renderandshowthefloatingpanel
有几个属性是使用浮动组件时值得注意的:
draggable-让浮动组件可以拖拽
shadow-定制浮动组件的阴影效果
alignTo()-让浮动组件对齐到一个特定元素
center()-让浮动组件相对于容器居中
CreatingCustomComponents自定义组件
CompositionorExtension组合还是继承当创建一个新的UI类时,必须决定这个类是引用其他组件的实例还是扩展这个组件。
推荐扩展最接近的组件添加自己需要的功能,这是因为使用继承的方式可以自动获得组件原有的自动生命周期管理能力,包括按须渲染、布局管理器提供的尺寸位置管理、从容器中删除的自动析构等。
扩展一个原有组件会让扩展出的组件隶属于组件层级中,这样比一个外部类引用并掌管ExtJS组件的实例要容易的多。
Subclassing子类化
ExtJS的
Ext.Component的子类,不添加任何功能:
12
3
Ext.define('My.custom.Component',{
extend:'Ext.Component'
});
TemplateMethods模板方法
ExtJS使用了
这意味着每一个继承链上的类都可以“贡献”一段包含特定逻辑的片段到组件的生命周期中。每一个类实现自己特殊行为的同时,还允许其他在继承链上的类继续贡献它们自己的逻辑。
一个例子就是
render方法。
render是个私有方法,是在
Component的父类
AbstractComponent中定义的,
render在组件生命周期中负责渲染阶段的初始化。
render不能被重写,但是
render过程中会调用
onRender,这个
onRender方法是允许子类去实现的,子类可以在这里增加专属于子类的逻辑,每一个
onRender方法必须在自己的额外逻辑之前调用父类的
onRender。
下图指示了
onRender模板方法是如何工作的。
render方法首先被调用(这是布局管理器完成的),
render方法不能被覆盖,它是ExtJS中的相关基类实现的,它会调用当前子类的
this.onRender(如果当前子类有实现
onRender),这会使得继续调用父类的
onRender,父类的
onRender会继续调用父类的,最后每个继承链上的类都贡献了自己的功能片段,并且控制回到
render方法中。
这有一个实现
onRender的例子
Ext.define('My.custom.Component',{
extend:'Ext.Component',
onRender:function(){
this.callParent(arguments);//callthesuperclassonRendermethod
//performadditionalrenderingtaskshere.
}
});
需要注意的是很多模板方法都有一个对应的事件。例如组件
render完成之后会触发
render事件。创建子类的时候最好是使用模板方法,而不是使用事件,因为模板方法一定会被执行,事件是可以被中断的(这里是我的补充:什么时候用事件,什么时候用模板方法?模板方法是面向你创建的子类的所有实例的,如果你需要增加的功能片段确实被所有实例需要,那一定要放在模板方法中,如果是某一个实例特殊需要的功能,请用事件实现,事件是可以对单独某个对象实现的)
下面列举的是
Component的子类中可以实现的模板方法:
initComponent这个方法被构造器调用,它被用来初始化数据,设置配置,添加事件
beforeShow这个方法在组件显示前调用
onShow允许组件显示的时候附加行为,调用父类的
onShow之后,组件变为可见
afterShow这个方法在组件显示完成后调用
onShowComplete这个方法在
afterShow执行完毕的时候调用
onHide允许组件隐藏的时候附加行为,调用父类的
onHide之后,组件变为不可见
afterHide这个放在组件隐藏完成后调用
onRender允许在渲染阶段附加行为
afterRender允许在渲染完毕时附加行为,在这个阶段,组件的
Element已经赋予了样式,该加的css类都已经加上,显示和启用与否的状态都标记完成
onEnable允许启用操作时附加行为,调用父类的
onEnable之后,组件变为启用
onDisable允许禁用操作时附加行为,调用父类的
onDisable之后,组件变为禁用
onAdded允许一个组件被添加到一个容器的时候附加行为,在这个阶段,组件已经在父容器的items中,调用父类的
onAdded之后,ownerCt引用被设置,如果配置了ref,refOwner这时也被设置
onRemoved允许一个组件从父容器中删除的时候附加行为,在这个阶段,组件已经从父容器的items中移除,但是还没有被销毁(如果父容器的autoDestroy设置为true,或者如果删除操作remove函数的第二个参数设置为true,组件就会被销毁),调用父类的
onRemoved之后,ownerCt和refOwner就会移除
onResize允许改变大小的时候附加行为
onPosition允许设置位置的时候附加行为
onDestroy允许销毁时附加行为,调用父类的
onDestroy之后,组件被销毁
beforeDestroy组件销毁前调用
afterSetPosition组件位置设置之后调用
afterComponentLayout组件布局完成时调用
beforeComponentLayout组件布局之前调用
WhichClassToExtend扩展那个类
选择最合适的类继承是个影响效率的问题,基类能提供的功能也是个问题。现在有种倾向是无论什么样的UI组件都从
Ext.Panel继承
Panel类有很多能力:
Border
Header
Headertools
Footer
Footerbuttons
Toptoolbar
Bottomtoolbar
ContainingandmanagingchildComponents
如果不需要这些功能,继承
Ext.Panel是浪费资源。
Component组件
如果创建的UI组件不需要包含任何其他组件,就比如只是对HTML片段的封装就可以满足需求的组件,推荐扩展
Ext.Component,例如下面的例子封装了HTMLimage元素,允许设置image的src,并且图片加载完成会触发
load事件:
Ext.define('Ext.ux.Image',{
extend:'Ext.Component',//subclassExt.Component
alias:'widget.managedimage',//thiscomponentwillhaveanxtypeof'managedimage'
autoEl:{
tag:'img',
src:Ext.BLANK_IMAGE_URL,
cls:'my-managed-image'
},
//AddcustomprocessingtotheonRenderphase.
//Adda‘load’listenertotheelement.
onRender:function(){
this.autoEl=Ext.apply({},this.initialConfig,this.autoEl);
this.callParent(arguments);
this.el.on('load',this.onLoad,this);
},
onLoad:function(){
this.fireEvent('load',this);
},
setSrc:function(src){
if(this.rendered){
this.el.dom.src=src;
}else{
this.src=src;
}
},
getSrc:function(src){
returnthis.el.dom.src||this.src;
}
});
用法:
varimage=Ext.create('Ext.ux.Image');
Ext.create('Ext.panel.Panel',{
title:'ImagePanel',
height:200,
renderTo:Ext.getBody(),
items:[image]
})
image.on('load',function(){
console.log('imageloaded:',image.getSrc());
});
image.setSrc('http://www.sencha.com/img/sencha-large.png');
这个例子仅作为例子,
Ext.Img可以在真实应用中使用。
Container容器
如果UI组件需要包含其他组件的能力,但是又不需要
Panel那么多功能
Ext.container.Container是个很好的选择。使用它有一点需要注意,记得使用
Layout管理子组件。
Ext.container.Container有如下模板方法:
onBeforeAdd这个方法在添加一个子组件之前调用,方法会被传入添加进来的子组件,你可能会对子组件进行一些修改,或者对容器自身做一些准备工作,返回false会中断添加操作。
onAdd这个方法在新组件被添加完成时调用,方法会传入新添加的组件,这个方法可以用来更新依赖子组件状态的内部结构
onRemove子组件被删除之后调用,用处跟
onAdd类似
beforeLayout组件布局它的子组件之前调用的方法
afterLayout组件布局它的子组件之后调用的方法
Panel面板
如果需求的UI组件必须有header,footer或者toolbar,
Ext.panel.Panel比较适合
注意
Panel也是个容器,也需要
Layout管理子组件
从
Panel扩展出的组件一般都是跟具体应用相关的,通常都聚合了其他组件在其中,一般都提供了操作内部组件的方法,比如在toolbar上有操作内部组件的按钮等
Panel有如下附加的模板方法:
afterCollapse组件折叠起来之后调用
afterExpand组件展开之后调用,与afterCollapse相对应
onDockedAdd工具条上有子组件添加之后调用
onDockedRemove工具条上有子组件被移除后调用
相关文章推荐
- extjs核心组件详解
- Extjs学习 图表Chart 序列组件详解(series)
- EXTJS 组件详解
- ExtJS4组件_form表单配置-属性-方法详解
- ExtJS 4 组件详解
- ExtJS4组件_Grid配置-属性-方法详解-案例
- ExtJS4组件_button按钮配置-属性-方法详解
- Extjs学习 图表Chart 坐标轴组件详解(axes)
- ExtJS4组件_Grid配置-属性-方法详解-案例
- ExtJS4组件_form表单配置-属性-方法详解
- ExtJS4组件_FieldSet配置-属性-方法详解
- extjs组件属性详解
- ExtJS 4 组件详解
- ExtJS4组件_button按钮配置-属性-方法详解
- ExtJS4组件_form表单配置-属性-方法详解
- ExtJs学习笔记基础篇(2)-Ext组件的使用
- UML组件图详解
- ExtJS2.0实用简明教程——组件的使用
- extjs的上传组件和HTML编辑器组件
- .NET 2.0 组件 BackgroundWorker 详解及示例