【问题标题】:Firing application wide events from button handlers从按钮处理程序触发应用程序范围的事件
【发布时间】:2015-07-17 22:48:05
【问题描述】:

我有这个网格面板:

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.fireEvent('testStart'...)

我使用this question 作为对事件和 Sencha 文档的常量引用,但找不到答案。

【问题讨论】:

    标签: extjs extjs4.1 extjs-mvc


    【解决方案1】:

    您在控制器范围内获得this.application

    鉴于您在这里明确使用 MVC,我会说最好坚持 MVC 概念;也就是说,为了可重用性,组件不应该知道哪个控制器使用它,而控制器应该知道它正在使用哪些组件。

    所以你真的应该在控制器中监听事件,并从那里触发一个应用程序事件。

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

    所以最好的办法是在视图中触发一个新事件:

    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 );
    }
    

    【讨论】:

    • 这是一个很好的答案,我认为这是我自己的想法,但是......在我看来,我将在控制器中监听此事件,发送一个应用程序范围的事件,然后将其捕获,这似乎很愚蠢在控制器上。难道没有别的办法了吗?另外......我不能以某种方式将控制器的范围声明为按钮吗?
    • 这里有两个控制器有问题吗?如果您想利用 MVC 模式,想法是(至少在 ExtJs 中)组件触发事件,这些事件在控制器中处理。如果组件代码与特定控制器有任何关系,则组件和它的控制器现在绑定在一起并且必须并排使用。
    • 好的。那我接受你的回答。请你们再快一点...:如果我在操作列中有两个项目,我如何在控制器中访问它们?因为'macro-test-list actioncolumn#id1' 什么也得不到。
    • 您最好检查点击处理程序的iItem 参数。
    • 10x 一百万。你是真正的 ExtJS 大师。
    【解决方案2】:

    在触发应用程序范围的自定义事件方面,在 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}; 
    

    此方法不限于控制器。任何组件都可以通过将组件对象作为输入参数范围来处理自定义事件。

    这是fiddle

    【讨论】:

    • 这太棒了......当你的班级被摧毁时,它甚至会为你断开活动。我预计会有事件流血,不得不断开自己的连接。
    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多