javascript - Extjs MVC 嵌套 View 事件和异步函数

标签 javascript ajax extjs extjs4

我正在开发一个 extJS 4.2 MVC 应用程序。 我定义了这个上下文菜单 View 对象:

Ext.define('XApp.view.message.inbox.CtxMenu', {
    extend : 'Ext.menu.Menu',
    alias : 'widget.inboxctxmenu',
    items : [ {
        itemId : 'buttonSetFlags',
        text : 'ToRead'
    }]
});

此上下文菜单是在我创建此网格(以及其他扩展网格)时构建的:

Ext.define('XApp.view.message.inbox.Grid', {
    extend: 'Ext.grid.Panel',
    alias: 'widget.inboxgrid',
    store: 'message.Inbox',

    initComponent : function(){
        this.menu = this.buildMenu();
        this.callParent(arguments);
        this.on({
            scope : this,
            itemcontextmenu : this.onItemContextMenu
        });
    },

    onItemContextMenu : function(grid, record, item, index, e, eOpts) {
        console.log('onItemContextMenu');
        e.stopEvent();      
        this.menu.showAt(e.getXY());
    },

    onDestroy : function(){
        console.log('destroy grid and menu');
        this.menu.destroy();
        this.callParent(arguments);
    },

    buildMenu : function(){
        return Ext.widget('inboxctxmenu');
    }
});

此代码摘自 Sencha blog第 2 点以避免嵌套对象上的内存泄漏。 现在在我的 Controller 中我想听

Ext.define('XApp.controller.Inbox', {
    extend : 'Ext.app.Controller',

    init : function(application) {
        this.control({
            "inboxctxmenu #buttonSetFlags" : {
                click : this.onFlagsSetter
            }
        });
    },
    onFlagsSetter : function(button, e, eOpts) {
        this.getController('Message').SetMessageStatus(1,"ToRead",this.getStore('message.Inbox').load);
    }
});

在这个 Controller 中,我调用另一个 Controller 函数,并且我想重新加载“message.Inbox”存储:

Ext.define('XApp.controller.Message', {
    extend : 'Ext.app.Controller',

    SetMessageStatus: function(id,statusToSet,callback) {
        Ext.Ajax.request({
            url : XApp.util.Util.serverUrl + 'api/message/SetMessageStatus/' + id + "/" + statusToSet,
            method : "GET",
            failure : function(response, options) {
                console.log('Failure' + response);
            },
            success : function(conn, response, options, eOpts) {
                console.log('Success');
                if (callback && typeof(callback) === "function") {  
                    console.log('Calling callback');
                    callback();  
                }  
            }
        });
    }
});

在此函数中,我使用 AJAX 进行异步调用,并且我想在 ajax 响应后重新加载 InboxController 的存储,但使用此表示法,控制台会抛出错误。 有调用异步函数并在成功或失败后启动回调的最佳实践吗? 另一个问题是: ExtJs MVC 监听嵌套 View 事件的最佳实践是什么(例如我的 ctxmenu 嵌套在网格中)?我读了 fireevent 和 bubbleevent,但我很困惑...请带我回到正确的方向...

最佳答案

JFYI 您示例中的上下文菜单未嵌套在网格中。菜单是 float 对象,因此它们位于通常的组件层次结构之外。

您遇到的错误是因为您没有将回调传递给 SetMessageStatus,而是传递了表达式 this.getStore('message.Inbox') 的结果。 load - 它计算为一个函数,但如果没有绑定(bind)到它的范围,它是无用的。阅读 this question's answers有关函数范围的更多说明。

采用天真的正面方法,修复看起来如下:

onFlagsSetter: function(button, e) {
    var me = this; // Important for the closure below

    this.getController('Message').SetMessageStatus(1, 'ToRead', function() {
        // Note that within the callback function, `this` is an object
        // entirely different from `this` in the above line, so we call
        // `getStore` on the captured scope instead.
        me.getStore('message.Inbox').load();
    });
}

但是,更好的方法是使用 Controller events :

Ext.define('XApp.controller.Inbox', {
    extend: 'Ext.app.Controller',

    init: function() {
        this.listen({
            component: {
                'inboxctxmenu #buttonSetFlags': {
                    click: this.onFlagsSetter
                }
            },
            controller: {
                '*': {
                    statusmessage: this.onStatusMessage
                }
            }
        });
    },

    onFlagsSetter: function(button) {
        this.fireEvent('setstatus', 1, 'ToRead');
    },

    onStatusMessage: function(success, response) {
        if (success) {
            this.getStore('message.Inbox').load();
        }
    }
});

Ext.define('Xapp.controller.Message', {
    extend: 'Ext.app.Controller',

    init: function() {
        this.listen({
            controller: {
                '*': {
                    setstatus: this.setMessageStatus
                }
            }
        });
    },

    setMessageStatus: function(id, statusToSet) {
        Ext.Ajax.request({
            url: ...,
            method: 'GET',

            failure: function(response) {
                this.fireEvent('statusmessage', false, response);
            },

            success: function(connection, response) {
                this.fireEvent('statusmessage', true, response);
            },

            // We are setting the above callbacks' scope to `this` here,
            // so they would be bound to the Controller instance
            scope: this
        });
    }
});

如您所见,通过使用 Controller 事件,我们将收件箱 Controller 与消息 Controller 解耦;他们不再直接调用彼此的方法,而是传递信息。代码更加简洁,并且关注点得到了正确的分离。

关于javascript - Extjs MVC 嵌套 View 事件和异步函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25809345/

相关文章:

javascript - 多个提交按钮仅首先初始化 javascript

c# - 抽象类可以作为 Controller 操作中的参数吗?

javascript - 有人可以向我解释我遇到的错误吗?

extjs - 在 ExtJS MVC 中使用 init 函数将数据加载到 Ext.data.Store

javascript - ExtJS 标签方向

javascript - 如何在用户每次返回主页时停止播放背景视频?

javascript - 为什么引用未声明的变量会引发引用异常,而引用未声明的属性却不会?

Javascript:将 setInterval() 函数内的变量计数增加 5

javascript - 如何控制加载查询功能的元素

javascript - Sencha Touch Checkbox 选择标签点击