ExtJs开发中应该注意到的几个问题
在享受Extjs进行前端开发的同时,我们经常会遇到一些容易忽略的问题,这些问题会随着代码量的增加以及需求场景的复杂化而逐步凸显出来,影响我们的产品维护与优化,以下就是几个常见的问题。
Ext.onReady()还是Ext.application() ?
在刚开始一个项目的时候,我们一般都会用到其中的一个函数,但是使用哪一个会更合适项目的开发呢?
这个取决我们打算将产品设计成什么样子,如果只是某些界面使用extjs来生成,或者在功能逻辑上不具有连接性,那么可以使用Ext.onReady(),甚至可以不用这两个函数中的任何一个。
如果是需要进行严格的产品功能设计,要在整体上使用extjs,那么最好还是使用Ext.application()作为项目入口更合适,因为这个函数与后面的结构有关
veiw + listeners 或者 controller + on?
一般来说,函数里面包含的是具体的事件,但是函数又是通过事件来触发的。为什么要通过事件来触发?因为使用事件来触发,可以避免界面没有渲染出来,但是函数已经开始调用
的问题,在extjs中常用的几种涉及到渲染问题的是afterrender
,show
,beforeshow
,hide
,beforehide
等,这些函数的结合使用,能够帮我们处理好渲染与程序的问题。
回到子标题上来看,在extjs的任何一个控件中都有一个属性——listeners
,这个属性是用来监听事件的,例如
1 xtype: 'panel', 2 title: 'panel title', 3 html: 'hello world!', 4 listeners: { 5 show:function(){ 6 console.log(this);//this is the object of the panel 7 }, 8 hide: function(){ 9 //... 10 } 11 }
这种写法很直接,将事件直接绑定到控件上,也很直观,找到控件就可以知道与之相关的逻辑。
然后我们来看另外一种写法,这种写法相对复杂一点,涉及到之前提到的函数Ext.application(),先看看这个函数的作用
1 Ext.application({ 2 name: 'App',//定义命名空间 3 appFolder: 'static/',//指定项目目录, 4 controller: [ 5 'App.controller.MainController'//需要在一开始就载入的controller 6 ], 7 launch: function() {//启动函数 8 Ext.create('App.view.Viewport');//创建一个我们自己定义的viewport 9 } 10 })
在这段代码中,viewport是必须要有的,可以通过函数创建,也可以由属性autoCreateViewport
来自动创建,这段代码的执行流程是:
通过这个流程,我们可以轻松的在控制器文件中添加对view中控件的事件绑定(绑定事件 != 触发事件)。这种方式比view + listenrers
要复杂,但是实现了视图与逻辑的分离,我们可以对一个视图进行控件或者一个布局进行多次使用,然后绑定不同的事件
用不用ID?
在使用ext中,我们经常会需要对某个控件绑定属性或者传值,但是却又没有这个控件对象,为了方便就在定义控件时加入id属性,然后通过Ext.getCmp()函数获取对象,这种方式虽然方便,但是不可取,原因我就不多说了。
在《精通extjs》这本书中提到了使用itemId+Ext.ComponentQuery.query()
来代替id+Ext.getCmp()
的组合。其实这种方式也不可取,因为Ext.ComponentQuery.query
会在所有的已存在控件中查找,然后会返回给你一个数组,容易出现对象错误(查到的不是你想要的)
其实页面布局的控件是存在上下关系的,只要我们找到了上级控件,就可以找到下级对象,反过来也是一样的,因此在理论上我们只需要定义一个id,就可以找到所有的控件(弹窗类的控件除外,后面单独讲),继续举例子
1 xtype: 'tabpanel', 2 id: 'demo_tabpanel', 3 items: [{ 4 xtype: 'panel', 5 itemId: 'first' 6 items:[{ 7 xtype: 'button', 8 action: 'search', 9 text:'search' 10 }] 11 }, { 12 xtype: 'panel' 13 itemId: 'second', 14 items:[{ 15 xtype: 'button', 16 action: 'search', 17 text:'search' 18 }] 19 }, { 20 // ... 21 }]
一个tabpanel是由许多个tab页面组成,每个tab页面又都是由许多个控件组成,每个控件中可能又包含有tbar,bbar等控件,但是我们只需要一个id,就可以获取到所有的tab里面的各种控件,然后通过活动tab页面的itemId或者状态,明确找到每一个id
1 var tabpanel = Ext.getCmp('demo_tabpanel'); 2 var firstPanel = tabpanel.down('panel[itemId=first]'); 3 var secondPanel = tabpanel.down('panel[itemId=second]') 4 或者 5 var firstPanel = tabpanel.items.getAt(0); 6 var secondPanel = tabpanel.items.getAt(1); 7 firstPanel.down('[action=search]').on('click', function(){ 8 //... 9 }) 10 secondPanel.down('[action=search]').on('click', function(){ 11 //... 12 })
通常约定如下:
button:添加属性'action'进行标识
form控件(textfield等):通过name属性区分
form中的控件(container等):添加name属性
tab页面:添加属性itemId
其他:name、alias以及其他方式
注重alias的作用
在定义一个类的时候,经常会写一个alias:
Ext.define('App.view.user.UserListPanel', { alias: 'widget.userListPanel', //... });
对于初学者来说,好像没有用到这个alias的地方,但是实际上这个alias的作用还是很大的,主要体现在以下四点上:
* 在controller中监听事件时,可以通过alias 给对象绑定事件:
this.control({ 'userListPanel': { //this is a alias name of the component afterrender: function() {} } })
* 在自动生成的id中,会看到alias的影子。通过extjs生成的id会自动生成`userListPanel-1121`类似这样的id,在调试中可以根据这种带alias的id找到需要的控件的HTML代码
* xtype中会使用到,一般我们定义一个button,都是这样写的
xtype: 'button'
text: 'button'
这里的xtype就是alias,在使用自定义的alias时,需要注意到引入的问题,没有引入类就使用自定义的alias,会出错的!!