Explain ExtJS 4 event handling
我最近开始学习extjs,并且很难理解如何处理事件。我没有任何以前版本的extjs的经验。
从阅读各种手册、指南和文档页面,我已经了解了如何使用它,但我不清楚它是如何工作的。我发现了一些针对旧版本的extjs的教程,但我不确定它们在extjs 4中的适用性。
我特别关注的是"最后一个词",比如
- 传递事件处理函数的参数是什么?是否有一组标准的参数总是被传递?
- 如何为我们编写的自定义组件定义自定义事件?我们如何启动这些自定义事件?
- 返回值(真/假)是否影响事件冒泡的方式?如果不是,我们如何控制事件从事件处理程序内部或外部冒泡?
- 有没有一种注册事件侦听器的标准方法?(到目前为止,我遇到了两种不同的方法,我不知道为什么使用每种方法)。
例如,这个问题让我相信一个事件处理程序可以接收到相当多的参数。我看过其他教程,其中只有两个处理程序参数。什么变化?
让我们从描述DOM元素的事件处理开始。
DOM节点事件处理首先,您不想直接使用dom节点。相反,您可能希望使用
1 |
我们需要添加
1 | var el = Ext.get('test_node'); |
现在让我们检查
click( Ext.EventObject e, HTMLElement t, Object eOpts )
知道所有这些,我们可以分配处理程序:
1 2 3 4 | // event name event handler el.on( 'click' , function(e, t, eOpts){ // handling event here }); |
小部件事件处理
小部件事件处理与DOM节点事件处理非常相似。
首先,小部件事件处理是通过使用
对于小部件,有两种分配处理程序的方法。第一个是用于方法(或
click( Ext.button.Button this, Event e, Object eOpts )
现在让我们使用
1 2 3 4 5 6 7 | var myButton = Ext.create('Ext.button.Button', { text: 'Test button' }); myButton.on('click', function(btn, e, eOpts) { // event handling here console.log(btn, e, eOpts); }); |
第二种方法是使用小部件的侦听器配置:
1 2 3 4 5 6 7 8 9 | var myButton = Ext.create('Ext.button.Button', { text: 'Test button', listeners : { click: function(btn, e, eOpts) { // event handling here console.log(btn, e, eOpts); } } }); |
注意,
1 2 3 4 5 6 7 | var myButton = Ext.create('Ext.button.Button', { text: 'Test button', handler : function(btn, e, eOpts) { // event handling here console.log(btn, e, eOpts); } }); |
自定义事件触发
首先,您需要使用addEvents方法注册事件:
1 | myButton.addEvents('myspecialevent1', 'myspecialevent2', 'myspecialevent3', /* ... */); |
使用
要触发事件,请使用FireEvent方法:
1 | myButton.fireEvent('myspecialevent1', arg1, arg2, arg3, /* ... */); |
1 2 3 4 | myButton.on('myspecialevent1', function(arg1, arg2, arg3, /* ... */) { // event handling here console.log(arg1, arg2, arg3, /* ... */); }); |
值得一提的是,在定义新的小部件时,插入addEvents方法调用的最佳位置是小部件的
1 2 3 4 5 6 7 8 9 10 | Ext.define('MyCustomButton', { extend: 'Ext.button.Button', // ... other configs, initComponent: function(){ this.addEvents('myspecialevent1', 'myspecialevent2', 'myspecialevent3', /* ... */); // ... this.callParent(arguments); } }); var myButton = Ext.create('MyCustomButton', { /* configs */ }); |
防止事件冒泡
为了防止起泡,可以使用
例如,让我们将click事件处理程序分配给按钮。如果未单击左键,则阻止默认浏览器操作:
1 2 3 4 | myButton.on('click', function(btn, e){ if (e.button !== 0) e.preventDefault(); }); |
触发应用程序范围的事件如何使控制器相互对话…
除了上面非常好的答案之外,我还想提到在MVC设置中非常有用的应用程序范围的事件,以实现控制器之间的通信。(Extjs4.1)
假设我们有一个带有选择框的控制器站(sencha mvc示例):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | Ext.define('Pandora.controller.Station', { extend: 'Ext.app.Controller', ... init: function() { this.control({ 'stationslist': { selectionchange: this.onStationSelect }, ... }); }, ... onStationSelect: function(selModel, selection) { this.application.fireEvent('stationstart', selection[0]); }, ... }); |
当选择框触发更改事件时,函数
在这个功能中,我们看到:
1 | this.application.fireEvent('stationstart', selection[0]); |
这将创建并激发一个应用程序范围的事件,我们可以从任何其他控制器监听该事件。
因此,在另一个控制器中,我们现在可以知道何时更改了工作站选择框。这是通过听
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | Ext.define('Pandora.controller.Song', { extend: 'Ext.app.Controller', ... init: function() { this.control({ 'recentlyplayedscroller': { selectionchange: this.onSongSelect } }); // Listen for an application wide event this.application.on({ stationstart: this.onStationStart, scope: this }); }, .... onStationStart: function(station) { console.info('I called to inform you that the Station controller select box just has been changed'); console.info('Now what do you want to do next?'); }, } |
如果选择框已更改,我们现在启动控制器
从Sencha文件:
应用程序事件对于具有多个控制器的事件非常有用。与在每个控制器中监听相同的视图事件不同,只有一个控制器监听视图事件并触发其他控制器可以监听的应用程序范围的事件。这也允许控制器在不知道或依赖彼此存在的情况下彼此通信。
在我的例子中:单击树节点以更新网格面板中的数据。
2016年更新,感谢@gm2008,评论如下:
在触发应用程序范围的自定义事件方面,在发布extjs v5.1之后,现在有了一种新的方法,即使用
当你触发事件时,你可以打电话:
注册事件处理程序时,调用:
此方法不限于控制器。任何组件都可以通过将组件对象作为输入参数范围来处理自定义事件。
在Sencha文档中找到:MVC第2部分
控制器事件侦听器的另一个技巧。
您可以使用通配符监视来自任何组件的事件:
1 2 3 4 5 | this.control({ '*':{ myCustomEvent: this.doSomething } }); |
只是想在上面的优秀答案中加上几便士:如果您正在处理pre-extjs 4.1,并且没有应用程序范围的事件,但需要它们,那么我一直在使用一种非常简单的技术,它可能有助于:创建一个简单的扩展可观察的对象,并定义您可能需要的应用程序范围内的事件。然后,您可以从应用程序的任何地方触发这些事件,包括实际的HTMLDOM元素,并通过从该组件中继所需的元素来从任何组件侦听这些事件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | Ext.define('Lib.MessageBus', { extend: 'Ext.util.Observable', constructor: function() { this.addEvents( /* * describe the event */ "eventname" ); this.callParent(arguments); } }); |
然后,您可以从任何其他组件:
1 | this.relayEvents(MesageBus, ['event1', 'event2']) |
并从任何组件或DOM元素中激发它们:
1 2 3 | MessageBus.fireEvent('event1', somearg); <input type="button onclick="MessageBus.fireEvent('event2', 'somearg')"> |
还有两件事我觉得很有帮助,即使它们不是问题的一部分,真的。
您可以使用
另一种方法是,将封装组件
1 2 3 4 | mycmp.on('show' function (mycmp, eOpts) { mycmp.subcmp.fireEvent('show', mycmp.subcmp, eOpts); }); |