Extjs 从按钮处理程序触发应用程序范围的事件

Extjs 从按钮处理程序触发应用程序范围的事件,extjs,extjs4.1,extjs-mvc,Extjs,Extjs4.1,Extjs Mvc,我有一个网格面板: Ext.define('BM.view.test.MacroList', { extend: 'BM.view.GridPanel', alias:'widget.macro-test-list', store: 'Tests', initComponent: function() { this.columns = [ { xtype:'actioncolumn', width:50,

我有一个网格面板:

Ext.define('BM.view.test.MacroList', {
extend: 'BM.view.GridPanel',
alias:'widget.macro-test-list',

store: 'Tests',

initComponent: function() {

    this.columns = [
        {
            xtype:'actioncolumn',
            width:50,
            items: [
            {
                icon: 'images/start.png',
                tooltip: 'Start Test',
                handler: function(grid, rowIndex, colIndex) {
                    this.application.fireEvent('testStart', grid.getStore().getAt(rowIndex)); 
                // application not defined here because 'this' is the button.
                }]
     }]
}
}
stratTest是一个可以在应用程序中的许多地方使用的功能,我希望它可以用作应用程序范围内的事件,但这些功能似乎只能从控制器中使用。
如何从该按钮内的处理程序调用
.application.firevent('testStart'…)


我一直在引用事件和Sencha文档,但找不到答案。

您可以在控制器范围内获得此应用程序

鉴于您在这里显然在使用MVC,我认为最好还是坚持MVC的概念;也就是说,为了可重用性,组件不应该知道控制器使用了什么,而应该知道控制器使用了什么组件

因此,您应该真正地侦听控制器中的事件,并从那里触发应用程序事件

问题是无法从控制器访问actioncolumn处理程序(它在
Ext.grid.column.Action
processEvent()
中内部调用)

因此,您最好在视图中启动一个新事件:

this.columns = [
    {
        xtype:'actioncolumn',
        ...
        items: [
        {
            ...
            handler: function( aGrid, aRowIndex, aColIndex, aItem, aEvent, aRecord ) {
                this.fireEvent( 'columnaction', aGrid, aRowIndex, aColIndex, aItem, aEvent, aRecord); }
        }]
 }]
还请注意,您可以为列定义全局处理程序,如下所示:

this.columns = [
    {
        xtype:'actioncolumn',

        handler: function( aGrid, aRowIndex, aColIndex, aItem, aEvent, aRecord ) {
            this.fireEvent( 'columnaction', aGrid, aRowIndex, aColIndex, aItem, aEvent, aRecord); }

        ...
        items: [
        {
            ...
        }]
 }]
然后在控制器中捕获此事件

init: function() {
    this.control({
        'macro-test-list actioncolumn':{
            columnaction: this.onAction
        }
    });
},

onAction: function( aGrid, aRowIndex, aColIndex, aItem, aEvent, aRecord ) {
    this.application.fireEvent( 'testStart', aGrid.getStore().getAt( aRowIndex ) );
}
顺便说一句,请注意,考虑到您正在尝试执行的操作,更干净的代码应该是:

onAction: function( aGrid, aRowIndex, aColIndex, aItem, aEvent, aRecord ) {
    this.application.fireEvent( 'testStart', aRecord );
}

APPNAME.getApplication.fireEvent()在应用程序范围内可用。

关于触发应用程序范围的自定义事件,在ExtJS V5.1发布后,现在有一个新方法,它使用Ext.GlobalEvents

触发事件时,您可以执行以下操作:

Ext.GlobalEvents.fireEvent('custom_event',args); 
注册事件的处理程序时,可以执行以下操作:

var obj = Ext.create('Ext.form.Panel', {
  // ....
});
Ext.GlobalEvents.on('custom_event', function(arguments){
  /* handler codes*/
}, obj}; 
此方法不限于控制器。任何组件都可以通过将组件对象作为输入参数作用域来处理自定义事件


这是一本书

这是一个很好的答案,我认为这是我自己的答案,但是。。。在我看来,我将在控制器中侦听此事件,发送一个应用程序范围的事件,然后在控制器上捕获该事件,这似乎很愚蠢。难道没有别的办法吗?而且我不能向按钮声明控制器的范围吗?这里有两个控制器有问题吗?如果您想利用MVC模式,其想法是(至少在ExtJs中)组件触发事件,这些事件在控制器中处理。如果组件代码与特定控制器有关,则组件及其控制器现在绑定在一起,必须并排使用。Ok。那我就接受你的回答。请你们中的一位再简单一点…:如果我在“操作”列中有两个项目,我如何在控制器中访问它们?由于
'macro-test-list actioncolumn#id1'
什么也得不到。您最好检查一下click处理程序的
iItem
参数。你是一个真正的ExtJS大师。这真是太棒了。。。当类被破坏时,它甚至会为您断开事件的连接。我原以为会发生流血事件,不得不切断自己的连接。