动态管理Ext.app.Application.controllers

jon*_*nny 10 model-view-controller frontend extjs

目前,我们的团队正在评估使用ExtJS进行前端转换大型企业Web应用程序(一种ERP系统,600多种独特屏幕)的可能性.该应用程序基于我们的开源pldia引擎

我们的引擎需要模型定义(它在编辑定义时变形数据库),具有某种控制器(内容模块)和演示文稿(具有生成实际js + html混合的代码的演示模块)

这个线程的一些人我们的团队有一个问题:

我们希望在服务器端拥有模型和视图,只是将JSON数据发送到前端

目前,洗脱核心开发人员(=我的团队,我们维护这个应用程序和eludia)已经做了一些步骤来变形引擎使用ExtJS作为前端

我的团队正在考虑:

  • 继续使用旧的内容模块作为服务器端代码
  • 使用服务器端模型定义动态生成ExtJS的模型文件,
  • 将Presentation模块转换为客户端ExtJS视图模块,并为每个屏幕编写客户端控制器但现在还有一个问题:ExtJS需要枚举Ext.app.Application中的所有控制器每次有人写新/转换屏幕从旧引擎他应该将它添加到此列表中

可以动态生成Ext.app.Application.controllers ...吗?

因此,这些问题由模糊性排序:

  • 你能说出任何使用ExtJS作为前端的足够大(600多个屏幕,优选的开源)MVC /非MVC应用程序吗?
  • 我们正在以正确的方式前进吗?

UPDATE

我应该试着缩小问题范围

在应用启动期间,您不需要一次加载所有控制器?

我想说的是,也许有可能以更"动态"的方式加载控制器:

  • 为打开的屏幕生成一个控制器js
  • 只要用户做某事(点击链接,按钮等),就会向Ext.app.Application.controllers添加新的内容:当需要新屏幕时

Pav*_*sky 6

按需使用控制器的最佳方法是动态加载它们并在需要时创建控制器实例.您还需要将控制器放在单独的js文件中,因此架构将如下所示:

//let's say you need to use controller User:
var controller = ControllerManager.get('User');//I believe you have some controller manager, similar to Sencha's Ext.ControllerManager
if(controller){
//use it here
}
else {
  loadScript([url of your controller script], controllerLoaded);
}
...
function controllerLoaded(){
//create controller instance here if needed and use it then
}
...
function loadScript(url, callback){

    var script = document.createElement("script")
    script.type = "text/javascript";

    if (script.readyState){  //IE
        script.onreadystatechange = function(){
            if (script.readyState == "loaded" ||
                    script.readyState == "complete"){
                script.onreadystatechange = null;
                callback();
            }
        };
    } else {  //Others
        script.onload = function(){
            callback();
        };
    }

    script.src = url;
    document.getElementsByTagName("head")[0].appendChild(script);
}
Run Code Online (Sandbox Code Playgroud)

更新 为了将新控制器集成到已运行中,Ext.app.Application您需要扩展Ext.app.Application并添加以下方法:

addController: function(name){
  //at this point your controller .js file should be already loaded into the DOM  
  var c = this.getController(name); //controller will be created automatically by name in this getter 
  //perform the same initialization steps as it would have during normal ExtJs process
  c.init(this);
  ?.onLaunch(this);
}
Run Code Online (Sandbox Code Playgroud)

顺便说一句,而不是使用自定义方法动态加载JavaScript文件,你可以使用ExtJs内置方法Ext.Loader:

/**
         * Load a script file, supports both asynchronous and synchronous approaches
         *
         * @param {String} url
         * @param {Function} onLoad
         * @param {Object} scope
         * @param {Boolean} synchronous
         * @private
         */
        loadScriptFile: function(url, onLoad, onError, scope, synchronous)
Run Code Online (Sandbox Code Playgroud)


Art*_*era 6

您最好的选择是依靠Ext.Loader,但不要使用loadScriptFile()上面建议的方法.

Ext 4引入了一个类系统.这种(许多)好处之一是dep-tree,它允许您根据需要管理所有组件间依赖关系和加载类.

以下是初始化加载程序的方法

Ext.Loader.setPath('App','/js/app');
Ext.Loader.setPath('WidgetsLibrary','/js/widgets');
Ext.Loader.setConfig({enabled: true});
Run Code Online (Sandbox Code Playgroud)

定义动态加载的控制器类:

Ext.define('App.controller.Menu', {
    extend: 'Ext.app.Controller',      // leave it as it is
    models: ['Event','User'],          // this assumes App.model.* prefix
    stores: ['Options','Permissions'], // this assumes App.store.* prefix
    views:  ['menu.Bar','SmartButton'],// this assumes App.view.* prefix
    requires: [
        'App.whatever.other.class',    // auto-load this class as a dependency
        'WidgetsLibrary.*',            // auto-load all classes in WidgetsLibrary
    ],

    init: function(){}

 // [...]
Run Code Online (Sandbox Code Playgroud)

现在动态加载你的控制器类(一个模型):

Ext.require(                   
    'App.controller.Menu',     // this auto-loads all dependencies 
    function(){ 
        // ... as soon as this class 
        //    and all its dependencies have loaded...
        var controller = Ext.create('App.controller.Menu');  // create an instance
        controller.init();                                   // launch init() method
    }
);
Run Code Online (Sandbox Code Playgroud)

奖励:通过使用类系统和加载器,您不必维护自己的控制器集合并检查控制器是否已加载.只需使用Ext.ClassManager.isCreated() 此处描述的方法.

if(Ext.ClassManager.isCreated('App.controller.Menu')){
    // ... controller has already been loaded and init ... 
}else{
    // we need to auto-load that controller using Ext.require()
}
Run Code Online (Sandbox Code Playgroud)

更多阅读:


Kal*_*exx 0

虽然我不知道这是否有效(从未尝试过),但我会看的是方法Ext.app.Application.getController()。来自API 参考

返回具有给定名称的控制器的实例。当控制器尚不存在时,就会创建它。

因此理论上,您可以使用动态定义的控制器调用 getController() ,它会创建它。

需要注意的是,我在查看 Ext 4 时了解到。控制器无法触发事件,因此要在控制器之间进行通信,您必须在对象上触发事件Application,如本文所述