【问题标题】:An Extjs App Calling another Extjs APP一个 Extjs 应用程序调用另一个 Extjs 应用程序
【发布时间】:2012-12-18 18:36:28
【问题描述】:

使用 Sencha Cmd 生成工作区并创建两个不同的应用程序后,我只想运行第一个应用程序,然后单击按钮后,它会调用第二个应用程序 :) 像一个主应用调用另一个子应用 有办法吗? 谢谢你的帮助

【问题讨论】:

  • 结果应该是什么?你调用静态服务(更新某些东西)或者你需要好的响应?
  • 第一个应用程序将是一个空面板和一个按钮。当我单击按钮时,第二个应用程序将加载到(第一个应用程序的)面板上。

标签: model-view-controller extjs extjs4.1 sencha-command


【解决方案1】:

您可以开发可以毫无问题地协同工作的独立模块。这两个概念根本没有冲突。

让我在这里分享我的经验。当我们开始我们当前的项目时(从头开始),另外两个团队正在开发另外两个应用程序,一段时间后我们应该将它们“集成”到一个大应用程序中。您不必是天才就能预测最终结果,对吧?当我们听说客户想要更多并行工作(更多团队开发模块)时,情况变得更糟。

第一个想法是使用 iframe,但 PoC 证明这是一个坏主意,因此我们停止了机器并开始设计可插拔架构。我们做得很好,因为目前我们能够轻松加载以隔离方式开发的模块(我们称之为插件)。例如,看看我们的文件夹结构是怎样的:

这是我们设置要加载的模块的元数据:

这有很多好处:

  • 模块可以并行开发,
  • 模块可以单独测试,
  • 模块可以动态加载、启用或禁用

当然,这不是 extjs 开箱即用的东西,但您可以这样做,因为它值得。

所以,简短的回答:您的问题不是应用程序的大小,而是它的结构。像我们一样遵循推荐的具有自定义文件夹结构的 MVC 模式。

更新:

关于插件元数据。应用程序主控制器只有一个职责:加载插件。这是通过以下代码完成的:

discoverPlugins: function () {
    var me = this;
    Ext.each(plugins(), function (d) {
        me.loadPluginController(d.controller);
    });

    App.History.notifyAppLoaded();
},

loadPluginController: function (controllerName) {
    try {
        var controller = App.current.getController(controllerName);
        controller.init(App.current);
    } catch (e) {
        console.log(controllerName + ' controller couldn\'t be loaded.' + e);
    }
},

每个插件控制器都充当调度程序,也就是说,有一个历史组件监听 url(在地址栏中),当它发生变化时,逐个插件迭代插件,请求处理 url。当插件能够处理请求的 url 时,该过程结束。
这是“操作”插件的调度程序配置:

constructor: function () {
    this.callParent(arguments);
    this.router.set({
        '!/operations/product/permissions/definition': this.viewPermissionsDefinition,
        '!/operations/product/accesslist/create': this.createProductAccessList,
        '!/operations/product/accesslist/{id}/edit': this.editProductAccessList,
        '!/operations/product/accesslist/{id}': this.viewProductAccessList,
        '!/operations/product/accesslist': this.viewProductAccessList,
        '!/operations/{...}': this.notFound,
        '!/operations': this.root
    });
} 

这是历史类代码的导航方法:

navigate: function (token) {
    var me = this,
        handled;

    if (token) {
        handled = false;
        for (var i = 0; i < me.routers.length; i++) {
            if (me.routers[i].processToken(token)) {
                handled = true;
                break;
            }
        }

        if (!handled) {
            App.current.fail(404, 'Resource not found.');
        }
    } else {
        App.current.gotoUrl('/servicedesk/search');
    }
},

重要的一点是插件只引用一个共享组件:渲染它们的中心区域:

refs: [
    { ref: 'main', selector: '#center-panel' }
],

这个引用被所有作为“AbstractPluginController”子类的插件控制器继承。这很重要,因为模块只知道它们的宿主。这就是我们可以并行开发的原因。

关于 AbstractPluginController,这个类有一些对所有插件控制器有用的核心功能,例如,为了在需要时而不是在此之前加载他们所有的控制器/视图/模型,这个类实现了动态控制器加载如下:

createControllerGetters: function (controllers) {
    var me = this;
    controllers = Ext.Array.from(controllers);
    Ext.Array.each(controllers, function (controllerName) {
        var parts = controllerName.split('.'),
            idx = parts.indexOf('controller'),
            significants = parts.slice(idx + 1),
            name = significants.map(function (e) { return Ext.String.capitalize(e); }).join(''),
            fn = 'get' + name + 'Controller';

        if (!me[fn]) {
            me[fn] = Ext.Function.pass(me.getController, [controllerName], me);
        }
    });
},

getController: function (controllerName) {
    this.controllerCache = this.controllerCache || {};
    var me = this,
        cached = me.controllerCache[controllerName];

    if (!cached) {
        me.controllerCache[controllerName] = cached = App.current.getController(controllerName);
        if (cached) {
            cached.init();
            cached.on('beforedestroy', function () {
                me.controllerCache[ref] = null;
            });
        }
    }

    return cached;
},

这允许我们指定模块具有的子控制器列表(因为主控制器只是一个初始化器和调度),并允许我们按需创建它们。

controllers: [
    'Operations.controller.ProductAccessListViewer',
    'Operations.controller.ProductAccessListEditor',
    'Operations.controller.ProductAccessListCreator'
],

总结:我认为主要有以下几点:

  1. 模块不必了解宿主应用程序的任何信息。
  2. 主要通过链接进行导航/通信
  3. 主机使用元数据执行的集成(插件也可以公开额外的元数据)
  4. 延迟加载控制器(他们用自己的视图做某事)

我希望这能给你一个想法。有很多细节和一些整合它们的技巧,但基本上,我想在这里展示的是一个模块化应用程序可以(或应该)用 extjs 开发,只需一点额外的努力。

【讨论】:

  • 我对您在此处发布的内容很感兴趣。我还没有见过这样的模块化应用程序。你有关于它的博客文章吗?
  • 感谢您的回答。我们曾经像您之前提到的那样使用 iframe。但我不明白元数据必须放在哪里?
  • 嗯,我猜根据这个例子,架构很难理解。正如@dbrin 提到的那样,这个想法听起来很酷,但如果没有插件架构核心或至少一些更详细的描述,它几乎无法采用。无论如何,在这个方向上的观点值得 +1 编辑 我也对有关此的更多信息非常感兴趣!
  • 你能给我们举个小例子吗?谢谢
  • 我已经用一些额外的细节更新了答案。可能它不符合你的所有期望,但它只是为了给你一个想法
【解决方案2】:

这个话题之前已经提出过。在这里查看建议: Using more than one controller with ExtJS 4 MVC

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-24
    • 2014-08-26
    • 1970-01-01
    相关资源
    最近更新 更多