Ext中的自定义事件是个好东西,对于某些特殊需求的实现,用它是个很不错的选择。然而经常有人问我为什么他们定义的事件无法被触发,最头痛的是不报错,怎么看都找不到原因。
今天我就来简单的分析一下,先来看如下一段代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | Ext.ns('www.ineeke.com'); www.ineeke.com.demo = Ext.extend(Ext.Panel, { constructor: function(){ www.ineeke.com.demo.superclass.constructor.call(this, { id: 'demo', tbar: [{ text: 'say', handler: function(){ this.fireEvent('say'); } }] }); this.addEvents('say'); this.on('say', this.saySomething, this); }, saySomething: function(){ Ext.Msg.alert('www.ineeke.com'); } }); |
上面的代码很简单,而且代码是100%没有错的!可是,当我按下say这个按钮时,saySomething()这个函数却没有执行。这是为什么呢?
其实,问题就在触发事件的那行代码上:
this.fireEvent('say');
而问题的关键就是这里的this,很多人没有搞清楚这里的this指的是谁,以为这里的this是和
this.addEvents('say');
中的this是同一个对象。其实前者指的是点击的按钮本身,而后者则是www.ineeke.com.demo这个组件。有关这些作用域的问题,见[JavaScript变量作用域]。
那么如何解决这个问题,实现我们的需求呢?下面给出三种我常用的方案:
第一种方案
为tbar中的按钮增加scope属性来指定this的指向。
1 2 3 4 5 6 7 8 | tbar: [{ text: 'say', handler: function(){ this.fireEvent('say'); }, //这个this指的是www.ineeke.com.demo scope: this }] |
第二种方案
使用Ext.getCmp()来实现。
1 2 3 4 5 6 | tbar: [{ text: 'say', handler: function(){ Ext.getCmp('demo').fireEvent('say'); } }] |
第三种方案
使用ownerCt来实现。
1 2 3 4 5 6 | tbar: [{ text: 'say', handler: function(){ this.ownerCt.ownerCt.fireEvent('say'); } }] |
三者的优缺点:
第一种:优点是简单易用,缺点是有局限性。
第二种:优点是getCmp()可以在任意时候获得到任意一个指定ID的组件,缺点当然就是必须指定一个ID(我想,这算是一个缺点吧)及效率较低。
第三种:优点是层次关系很清晰直观,缺点是如果组件嵌套的层次过多,这个可就有的写了
。
就我写了这么久(也不是很久啦,O(∩_∩)O哈哈~)的ExtJS而言,第二种方案我从未使用过,用的最多的是第一种,第三种次之。因为如果代码组织的清晰规范的话,第一种和第三种就足够了,第二种根本就用不到,而且第二种的效率也低。

