【问题标题】:ExtJS 4.1 Call One Controller From AnotherExtJS 4.1 从另一个控制器调用一个控制器
【发布时间】:2015-10-07 20:50:59
【问题描述】:

注意:我对 javascript 完全一无所知。

我已将我的 ExtJS 4.1 MVC 应用程序分解为几个控制器,例如:

/app/controller/Auth
    |          |Quiz
    |          |Result
    |          |Blah...
    |model/...

我想通过调用我的Auth 和@987654324 中的函数 来响应“事件”,而不是DOM 事件,而是Ext.form.action.Submit.success 事件@控制器。第一部分的总结代码在这里:

// File: app/controller/Auth.js
attemptLogin : function() {
    var form = Ext.ComponentQuery.query('#loginpanel')[0].form;
    if (form.isValid()) {
        form.submit({
        success : function(form, action) {
            // THIS IS THE FUNCTION FROM THE CURRENT CONTROLLER
            Assessor.controller.Auth.prototype.finishLogin();
            // THIS IS THE FUNCTION FROM THE OTHER CONTROLLER
            Assessor.controller.Quiz.prototype.setupAssessment();
        },

这可行,但感觉不对。有没有合适的方法来做到这一点?似乎我应该触发一个由两个控制器监听的独特事件,但我不明白如何使用Ext.Event 来做到这一点。有什么指导吗?

谢谢!我非常感谢所有伟大的想法和建议。

【问题讨论】:

  • 我会使用应用程序事件总线。这就是谷歌为 GWT 所做的。基本上,监听应用程序上的事件。在应用程序上触发事件。

标签: events extjs controller


【解决方案1】:

对我来说,从表单触发一个自定义事件并在你的两个控制器中简单地听它是有意义的,就像你在这里所说的那样:

看来我应该触发一个独特的事件,双方都在听 控制器

// File: app/controller/Auth.js
attemptLogin : function() {
    var form = Ext.ComponentQuery.down('#loginpanel').form;
    if (form.isValid()) {
        form.submit({
        success : function(form, action) {
            // fire the event from the form panel
            form.owner.fireEvent('loginsuccess', form.owner);
        },

然后在您的每个控制器中,您可以使用 Controller#control 收听它,如下所示:

Ext.define('YourApp.controller.Auth', {
    extend: 'Ext.app.Controller',

    init: function() {
        var me = this; 

        me.control({

            '#loginpanel': {

                loginsuccess: me.someHandler

            }
        });
    },

    someHandler: function(form) {
        //whatever needs to be done
        console.log(form);
    }
}

然后将相同的内容添加到您的 Quiz 控制器:

Ext.define('YourApp.controller.Quiz', {
    extend: 'Ext.app.Controller',

    init: function() {
        var me = this; 

        me.control({

            '#loginpanel': {

                loginsuccess: me.someOtherHandler

            }
        });
    },

    someOtherHandler: function(form) {
        //whatever needs to be done
        console.log(form);
    }
}

我已经在 4.1.0 和 4.1.1 中成功使用了这种方法

【讨论】:

  • 我们使用与此类似的方法,但是因为我们不喜欢将某些事件绑定到特定视图,所以我们使用 Ext.Viewport.fireEvent("eventname") 触发我们的事件。然后,您可以使用视口引用在任何控制器中侦听它们。
  • @mmigdol,如果您从 Viewport 触发事件,您如何对控制器进行单元测试?
  • @AlexanderTokarev,只需从测试工具中的视口触发事件......或者我可能误解了你的问题?
  • @mmigdol,这意味着为了测试控制器,您需要实例化视口及其所有子项。还是您使用某种仅用于测试的视口?
  • @AlexanderTokarev,没错。我的单元测试通常是实例化单个视图和/或其关联控制器的独立应用程序
【解决方案2】:

应该是这样的

Assessor.controller.Auth.prototype.finishLogin.apply(this, arguments)

或类似的东西(为了有一个正确的 this 引用指向方法的“所有者”,即控制器对象)

但是,为什么要使用这种非正统的方式来调用当前控制器的方法。只需为成功回调设置scope,然后调用this.finishLogin()。

form.submit({
    success : function(form, action) {
        // THIS IS THE FUNCTION FROM THE CURRENT CONTROLLER
        this.finishLogin();
        ...
    },
    scope: this
});

此外,您可以使用 Controller#getController 检索另一个控制器实例。

this.getController('Assessor.controller.quiz').setupAssignment();

然后,如果您的控制器方法不相互依赖,您可以让它们都监听同一个事件。

另一种解决方案是在登录完成后触发自定义事件。您可以在应用程序对象上执行此操作

this.application.fireEvent('logincomplete');

在控制器的 init 方法中:

this.application.mon('logincomplete', this.setupAssignment, this);

请注意,您不能通过Controller#control 收听这些事件 - 请参阅 Alexander Tokarev 的博客文章,获取 Ext 的补丁以实现此目的。

【讨论】:

  • 你不必调用this.application.getController(),只需调用this.getController()即可。
  • 我一直无法弄清楚如何获得this 的正确范围。而且,this.getController 的所有变体。 this.application 失败是因为,我相信,范围不合适。由于对 JS 的理解不够深入,所以想不通。
【解决方案3】:

没有在控制器之间触发事件的标准方法,但可以通过一些自定义技巧来实现。查看我最近的blog post

【讨论】:

  • 有可能:使用 this.getController('ControllerName').foo();
  • @EvanTrimboli 当然可以,但是这种方式将控制器绑定得太紧,不符合我的口味。您需要创建 all 其他控制器并使用您调用的 all 方法将它们存根,以测试您现在正在使用的方法。触发事件更好更干净。
【解决方案4】:

我也一直在寻找这个,您只需要 Asanda.app.getController('quiz').setupAssignment();,其中 Asanda 是您的应用程序的名称

【讨论】:

  • 能否请您详细说明您的答案,添加更多关于您提供的解决方案的描述?
  • 不明白这个问题。如果在上面阅读,这就是您从不同控制器调用函数的方式。您需要指定文件在哪里。例如
【解决方案5】:

如果你必须在控制器之间发送事件,你应该使用 MessageBus:

Ext.define('MyApp.utils.MessageBus', {
        extend : 'Ext.util.Observable'
});

将消息总线存储在全局变量中

MsgBus = Ext.create('MyApp.utils.MessageBus');

你必须发送事件的地方:

MsgBus.fireEvent('eventName',eventArg_1,eventArg_2);

您必须在哪里接收事件:

MsgBus.on('eventName', functionHandler,scope); //scope is not mandatory
...
functionHandler:function(eventArg_1,eventArg_2){
...
//do whatever you want
...
}

【讨论】:

    猜你喜欢
    • 2015-09-07
    • 2016-04-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-13
    • 2016-01-05
    • 1970-01-01
    相关资源
    最近更新 更多