динамически управлять Ext.app.Application.controllers - PullRequest
10 голосов
/ 11 октября 2011

В настоящее время наша команда оценивает возможность конвертирования крупного корпоративного веб-приложения (разновидность ERP-системы, более 600 уникальных экранов) с использованием ExtJS для внешнего интерфейса. Приложение было построено на нашем eludia engine

с открытым исходным кодом.

Наш движок требует определения модели (он изменяет базу данных при редактировании определения), имеет какой-то контроллер (Модули контента) и Presentation (Модули презентаций с кодом, который генерирует реальное сочетание js + html)

Как и некоторые люди из этой темы, у нашей команды есть проблема:

Мы бы хотели иметь Model и View на стороне сервера и просто отправлять JSON-данные в интерфейс

В настоящее время разработчики ядра eludia (= моя команда, мы поддерживаем и это приложение, и eludia) сделали несколько шагов к движку трансформации, чтобы использовать ExtJS в качестве внешнего интерфейса

Моя команда рассматривает:

  • продолжить использование старых модулей контента в качестве кода на стороне сервера
  • генерация файлов модели для ExtJS на лету с использованием определения модели на стороне сервера,
  • преобразование модулей Presentation в клиентские модули представления ExtJS и запись контроллеров на стороне клиента для каждого экрана Но теперь есть еще одна проблема: ExtJS требует перечислить все контроллеры в Ext.app.Application Каждый раз, когда человек пишет новый / конвертирует экран из старого движка, он должен добавить его в этот список

Может ли Ext.app.Application.controllers ... генерироваться динамически?

Поэтому эти вопросы, упорядоченные по нечеткости:

  • Можете ли вы назвать какое-нибудь достаточно большое (более 600 экранов, предпочтительно с открытым исходным кодом) приложение MVC / non MVC, которое использует ExtJS в качестве внешнего интерфейса?
  • Правильно ли мы движемся?

UPDATE

Я должен попытаться сузить вопрос

Не нужно загружать все контроллеры одновременно во время запуска приложения?

То, что я пытаюсь сказать, возможно, возможно загружать контроллеры в более «динамическом» подходе:

  • генерировать один контроллер JS для открытого экрана
  • добавить новые в Ext.app.Application.controllers всякий раз, когда пользователь что-то делает (нажимает на ссылку, кнопку и т. д.): когда необходим новый экран

Ответы [ 5 ]

6 голосов
/ 17 ноября 2011

Ваша лучшая ставка должна зависеть от Ext.Loader, но не использовать loadScriptFile() метод, как предложено выше.

Ext 4 вводит систему классов.Одним из (многих) преимуществ этого является деп-дерево, которое позволяет вам управлять всеми своими межкомпонентными зависимостями и классами загрузки по мере необходимости.

Вот как вы инициализируете загрузчик

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

Определите динамически загружаемый класс контроллера:

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(){}

 // [...]

Теперь динамически загружаем ваш класс контроллера (макет):

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

БОНУС: используя систему классов и загрузчик, вам не нужно поддерживать собственную коллекцию контроллеров и проверять, загружен контроллер или нет.Просто используйте метод 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()
}

Подробнее:

6 голосов
/ 30 октября 2011

Лучший способ использовать контроллер по требованию - это динамически загружать его и создавать экземпляры контроллеров, когда это необходимо.Также вам нужно поместить свои контроллеры в отдельные 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);
}

ОБНОВЛЕНИЕ Чтобы интегрировать новый контроллер в уже запущенный 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);
}

Кстати, вместо использования пользовательского метода для динамической загрузки файла 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)
1 голос
/ 01 ноября 2011

Мы только что прошли через наше веб-приложение.~ 250 экранов.Да, мы загружаем наши контроллеры динамически.

Время создания экрана с использованием Ext.JS примерно на 400% быстрее, чем с использованием YUI, который был нашей предыдущей платформой.Приятно было то, что мы могли сохранить объект YUI Connect, который работает с большей эффективностью, чем версия Ext.JS.

У нас есть класс App, который управляет загрузкой и инициализацией контроллеров Ext.JS.Здесь мы используем единственный другой класс YUI в нашем коде, который является YUI.get (YUI.get.script).Просто убедитесь, что вы не загружаете контроллер дважды в одном и том же сеансе.

Я предполагаю, что вы хотите динамически загружать эти контроллеры в течение времени загрузки (с чем мы и боролись изначально).EXTEND, EXTEND, EXTEND.

Ext.define('namespace.classname', {
{
    extend: 'Ext.form.panel',
    // your code here
}

Это снизит общую загрузку кода и ускорит инициализацию.

0 голосов
/ 28 октября 2011

Я задавал такой же вопрос здесь: http://www.sencha.com/forum/showthread.php?151220-Adding-controllers-views-dynamically-in-Ext-MVC-pattern

Не похоже, что это хорошо поддерживается в текущем Ext 4. Я с тех пор переключил направление и не использую архитектуру MVC, которую обеспечивает Ext, и вместо этого использую те же методы, которые я использовал в Ext 3, который добавляет / загрузка дополнительных компонентов в определенные обработчики (щелчки по кнопкам или ссылкам, зависания, поиски и т. д.).

В моем приложении все мои компоненты являются пользовательскими расширениями базовых классов Ext, и в действительности они ведут себя во многом как контроллер, а суперклассы - это представление. Например, если у меня есть расширение Ext.panel.Panel, кроме начальной конфигурации items и layout, я не делаю ничего, что влияет на представление (все это обрабатывается в базовом классе). Большая часть класса прикрепляет обработчики и другие элементы к панели для обеспечения специфичного поведения приложения, которое в основном является определением контроллера. На мой взгляд, он не идеален, но лучше текущей альтернативы.

Если вам нужны примеры того, о чем я говорю, или у вас есть вопросы по поводу моей конкретной реализации, дайте мне знать, и я буду рад помочь.

0 голосов
/ 26 октября 2011

Хотя я не знаю, сработает ли это (никогда не пытался), я бы посмотрел на метод Ext.app.Application.getController().Из ссылки api :

Возвращает экземпляр контроллера с заданным именем.Когда контроллер еще не существует, он создан.

Так что теоретически вы можете вызвать getController () с вашим динамически определенным контроллером, и он создаст его.Я узнал, глядя на Ext 4. Контроллеры не могут запускать события, поэтому для связи между контроллерами нужно запускать события на объекте Application, описанном в в этом посте

...