Магистральные магистрали и модули RequireJS - программирование
Подтвердить что ты не робот

Магистральные магистрали и модули RequireJS

Я начинаю широкомасштабное javascript-приложение с Marionette. Приложение Marionette имеет концепцию модулей приложений, а RequireJS также используется для разбиения кода на модули,

В настоящее время у меня есть это для начала моего приложения:

require([ "jquery", "underscore", "backbone", "marionette" ],
function ($, _, Backbone, Marionette) {
    $(function() {

        App = new Marionette.Application();
        App.addInitializer(function(options) {
            App.addRegions({
                mainArea: "#mainArea"
            });
        });

        App.on("start", function() {
            // done starting up, do stuff here
        });

        App.start();
    });
});

Если бы я хотел добавить представление, сделал бы я что-то вроде следующего в файле?

require([ "jquery", "underscore", "backbone", "marionette" ],
function($, _, Backbone, Marionette) {

    App.module("FirstView", function(FirstView, App, Backbone, Marionette, $, _) {
        return Marionette.ItemView.extend({
            //define view stuff in here
         });
    });

});

Я не уверен, как бы я смог запустить этот код, любая помощь очень ценится

4b9b3361

Ответ 2

IMHO Мне нравится отличаться от указанной выше точки зрения. Модули Marionette предназначены для простой альтернативы форматам модулей RequireJS (и других).

Мне нравится сопоставлять модули Require.js и модули Marionette.js с концепциями сборки и пространства имен С#. Модули Marionette.js помогают нам группировать определения различных строительных блоков на основе функциональности, в то время как Require.js можно использовать для загрузки/вставки зависимостей.

Опять же, это мое мнение/понимание (основанное на дискуссиях с Дэвидом Сулком в его книге "Структурирование базового кода с помощью требований и модулей Marionette" ), что помогло мне в реализации. В некотором смысле мы можем использовать Marionette.js и Require.js вместе, как описано ниже.

Ниже приведен пример небольшого приложения библиотеки (образец), которое можно найти в Интернете @https://github.com/srihari-sridharan/LibraryManagement. Приведенный ниже код (исключая незначительные биты и фрагменты) создает объект приложения и выводит список книг после инициализации. Пожалуйста, найдите здесь - https://github.com/srihari-sridharan/LibraryManagement/blob/master/app/js/app.js

define([
    'marionette',
    'modules/config/marionette/regions/dialog'], function (Marionette) {

    // Create the application object
    var LibraryManager = new Marionette.Application();

    // Add regions to the application object
    LibraryManager.addRegions({
        //Header
        headerRegion: "#header-region",
        //Main
        mainRegion: "#main-region",
        //Footer
        footerRegion: "footer-region",
        //Overlay Dialog
        dialogRegion: Marionette.Region.Dialog.extend({
            el:"#dialog-region"
        })
    });

    // Subscribe to Initialize After event.
    LibraryManager.on('initialize:after', function() {
        if(Backbone.history){
            require(['modules/books/booksModule', 'modules/about/aboutModule'], function (){
                Backbone.history.start();    
                if(LibraryManager.getCurrentRoute() === ''){
                    LibraryManager.trigger("books:list");
                }                    
            });
        }
    });

    // Return the application object.
    return LibraryManager;
});

Далее мы определяем модуль/подмодули на основе функциональности. Это также будет иметь специфический для модуля маршрутизатор и будет управлять контроллерами и обрабатывать маршруты. Обратите внимание на необходимость вызова контроллеров. Этот код присутствует в https://github.com/srihari-sridharan/LibraryManagement/blob/master/app/js/modules/books/booksModule.js

define(['app'], function (LibraryManager) {
    // Define a new module for Books - BooksModule
    LibraryManager.module('BooksModule', function (BooksModule, LibraryManager, Backbone, Marionette, $, _) {

        BooksModule.startWithParent = false;

        BooksModule.onStart = function () {
            console.log('Starting BooksModule.');
        };

        BooksModule.onStop = function () {
            console.log('Stopping BooksModule.');
        };

    });

    // Define a new module for a Router specific to BooksModule
    LibraryManager.module('Routers.BooksModule', function (BooksModuleRouter, LibraryManager, Backbone, Marionette, $, _) {

        BooksModuleRouter.Router = Marionette.AppRouter.extend({
            appRoutes: {
                'books': 'listBooks',
                'books(?filter:=criterion)': 'listBooks',
                'books/:id': 'showBook',
                'books/:id/edit': 'editBook'
            }
        });

        var executeAction = function (action, arg) {
            LibraryManager.startSubModule('BooksModule');
            action(arg);
            LibraryManager.execute('set:active:header', 'books');
        };

        var API = {
            // This is where we are using / referring to our controller
            listBooks: function (criterion) {
                require(['modules/books/list/listController'], function (ListController) {
                    executeAction(ListController.listBooks, criterion);
                });
            },

            showBook: function (id) {
                require(['modules/books/show/showController'], function (ShowController){
                    executeAction(ShowController.showBook, id);
                });
            },

            editBook: function (id) {
                require(['modules/books/edit/editController'], function (EditController) {
                    executeAction(EditController.editBook, id);
                });
            }

        };

        // Navigating routes.
        LibraryManager.on('books:list', function () {
            LibraryManager.navigate('books');
            API.listBooks();
        });

        LibraryManager.on('books:filter', function(criterion) {
            if(criterion){
                LibraryManager.navigate('books?filter=' + criterion);
            }
            else{
                LibraryManager.navigate('books');
            }
        });

        LibraryManager.on('book:show', function (id) {
            LibraryManager.navigate('books/' + id);
            API.showBook(id);
        });

        LibraryManager.on("book:edit", function(id){
            LibraryManager.navigate('books/' + id + '/edit');
            API.editBook(id);
        });

        LibraryManager.addInitializer(function () {
            new BooksModuleRouter.Router({
                controller: API
            });
        });
    });

    return LibraryManager.BooksModuleRouter;
});

Наконец, мы имеем определения для наших представлений, моделей и контроллеров. Эти определения будут привязаны к объектам модуля/вспомогательного модуля.

Код вида показан ниже. Посмотрите на методы .extend(). Они присваиваются переменным, прикрепленным к модулю BooksModule.List.View. https://github.com/srihari-sridharan/LibraryManagement/blob/master/app/js/modules/books/list/listView.js

define(['app',
        'tpl!modules/books/list/templates/layout.html',
        'tpl!modules/books/list/templates/panel.html',
        'tpl!modules/books/list/templates/none.html',
        'tpl!modules/books/list/templates/list.html',
        'tpl!modules/books/list/templates/listItem.html'], 
    function (LibraryManager, layoutTemplate, panelTemplate, noneTemplate, listTemplate, listItemTemplate) {

        LibraryManager.module('BooksModule.List.View', function(View, LibraryManager, Backbone, Marionette, $, _) {

            View.Layout = Marionette.Layout.extend({

                template: layoutTemplate,

                regions:{
                    panelRegion: '#panel-region',
                    booksRegion: '#books-region'
                }

            });

            View.Panel = Marionette.ItemView.extend({
                // More code here!
            });

            View.Book = Marionette.ItemView.extend({                
                // More code here!
            });

            var NoBooksView = Marionette.ItemView.extend({
                template: noneTemplate,
                tagName: "tr",
                className: "alert"
            });

            View.Books = Marionette.CompositeView.extend({
                // More code here!
            });
        });
    return LibraryManager.BooksModule.List.View; // Return the definition.
});

Ниже приведен код контроллера. Это вызывается из кода в booksModule.js. Определение контроллера присоединено к модулю BooksModule.List.

define(['app', 'modules/books/list/listView'], function (LibraryManager, View) {

    LibraryManager.module('BooksModule.List', function (List, LibraryManager, Backbone, Marionette, $, _) {

        List.Controller = {

            listBooks: function (criterion) {

                require(['common/views', 'entities/book'], function (CommonViews) {

                    var loadingView = new CommonViews.Loading();
                    LibraryManager.mainRegion.show(loadingView);

                    var fetchingBooks = LibraryManager.request('book:entities');
                    var booksListLayout = new View.Layout();
                    var booksListPanel = new View.Panel();

                    require(['entities/common'], function (FilteredCollection) {

                        $.when(fetchingBooks).done(function (books) {
                            // More code here!
                            });

                            if(criterion){
                                filteredBooks.filter(criterion);
                                booksListPanel.once('show', function () {
                                    booksListPanel.triggerMethod("set:filter:criterion", criterion);
                                });
                            }

                            var booksListView = new View.Books({
                                collection: filteredBooks
                            });

                            booksListPanel.on('books:filter', function (filterCriterion) {
                                filteredBooks.filter(filterCriterion);
                                LibraryManager.trigger("books:filter", filterCriterion);
                            });

                            booksListLayout.on("show", function(){
                                booksListLayout.panelRegion.show(booksListPanel);
                                booksListLayout.booksRegion.show(booksListView);
                            });

                            booksListPanel.on('book:new', function () {

                                require(["modules/books/new/newView"], function (NewView) {
                                        // More code here!
                                    });

                                    LibraryManager.dialogRegion.show(view);
                                });
                            });

                            booksListView.on('itemview:book:show', function (childView, model) {
                                LibraryManager.trigger("book:show", model.get('id'));
                            });

                            booksListView.on('itemview:book:edit', function(childView, model) {
                                require(['modules/books/edit/editView'], function (EditView) {
                                    // More code here!
                                    LibraryManager.dialogRegion.show(view);
                                });
                            });

                            booksListView.on("itemview:book:delete", function (childView, model) {
                                model.destroy();
                            });

                            LibraryManager.mainRegion.show(booksListLayout);

                        });

                    });

                });

            }

        }

    });

    return LibraryManager.BooksModule.List.Controller; // Return the definition.
});

Таким образом, модули require.js и марионеточные модули могут сосуществовать. Ниже приведены преимущества.

  • Значительная очистка организации исходного кода и более четкое разделение проблем.
  • Методы запуска и остановки модуля обеспечивают предоставление инициализации и очистки объектов.
  • Когда вы моделируете функциональные возможности и вспомогательные функции как модули и вспомогательные модули, мы имеем более подробный контроль над тем, что находится в памяти, а что нет.
  • Кроме того, определение модуля можно разделить на несколько файлов.

Пожалуйста, разместите свои мысли. Спасибо за чтение.

PS: на основе приведенной выше точки обзора найдите изменения в приведенном ниже примере:

require([ "jquery", "underscore", "backbone", "marionette" ],
function($, _, Backbone, Marionette) {
    App.module("FirstView", function(FirstView, App, Backbone, Marionette, $, _) {
        FirstView.View = Marionette.ItemView.extend({
            //define view stuff in here
        });

        return FirstView.View;
    });
});