2012-07-06 17 views
16

Estoy comenzando una aplicación de javascript a gran escala con Marionette. Una aplicación de marionetas tiene un concepto de módulos de aplicación y RequireJS también se utiliza para romper el código en módulos,Backbone Marionette y RequireJS Modules

Actualmente tengo unas pocas cosas para el inicio de mi solicitud:

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

Si quisiera añadir un punto de vista sería ¿Hago algo como lo siguiente en un archivo?

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

}); 

No estoy seguro de cómo me gustaría obtener este código se ejecute en realidad, cualquier ayuda es muy apreciada

Respuesta

23
módulos de marioneta

están destinados a ser una alternativa sencilla a RequireJS (y otros formatos) del módulo. No recomendaría usarlos juntos, como se ha señalado en el wiki:

https://github.com/marionettejs/backbone.marionette/wiki/AMD-Modules-vs-Marionette's-Modules

+0

tiene sentido. ¡Gracias! Voy a utilizar RequireJS, porque supongo que si utilizara módulos de Marionette tendría que pegar todos mis archivos de aplicación en etiquetas de script en la cabecera, como en BBCloneMail, estoy tratando de evitar hacer eso. –

+1

No recomiendo usar varias etiquetas de script. BBCloneMail no es un ejemplo de hacerlo bien. :) Los proyectos reales tienen pasos de construcción que concat y minify. r.js lo hace para requerir módulos, o se puede hacer con otras herramientas como Rails asset Pipeline o grunt.js, o muchas otras herramientas. –

+2

Aquí hay un enlace de actualización para usar Marionette con RequireJS. (El repositorio github se movió.) Https://github.com/marionettejs/backbone.marionette/wiki/Using-marionette-with-requirejs –

4

mi humilde opinión me gusta ser diferente del punto de vista se ha dicho "módulos de marioneta están destinados a ser una alternativa sencilla a RequireJS (y otros) formatos de módulos ".

Me gusta hacer una comparación entre los módulos Require.js y los módulos Marionette.js con los conceptos de ensamblado y espacio de nombre de C#. Los módulos de Marionette.js nos ayudan a agrupar las definiciones de varios componentes basados ​​en la funcionalidad, mientras que Require.js se puede usar para cargar/inyectar dependencias.

Una vez más, este es mi punto de vista (basado en las discusiones con David Sulc en su libro 'Estructurar el código backbone con RequireJS y Marionette Modules'), que ha ayudado en mi implementación. De alguna manera podemos usar Marionette.js y Require.js juntos como se describe a continuación.

El siguiente ejemplo es una pequeña aplicación del Administrador de bibliotecas (muestra) que se puede encontrar en línea en https://github.com/srihari-sridharan/LibraryManagement. El código siguiente (omisión de bits y piezas insignificantes) crea el objeto de la aplicación y representa la lista de libros después de la inicialización. Por favor, encontrar aquí - 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; 
}); 

A continuación se definen los módulos/submódulos en base a la funcionalidad. Esto también tendrá un enrutador específico de módulo y cableará los controladores y manejará las rutas. Tenga en cuenta que requieren una llamada a los controladores. Este código está presente en 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; 
}); 

Por último tenemos las definiciones de nuestros puntos de vista, los modelos y controladores. Estas definiciones estarán vinculadas a los objetos del módulo/sub módulo.

El código de la vista se muestra a continuación. Mire los métodos .extend(). Se asignan a las variables adjuntas al submódulo 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. 
}); 

El código del controlador se muestra a continuación. Esto se llama desde el código en booksModule.js. La definición del controlador se adjunta al submódulo 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. 
}); 

Por lo tanto, los módulos require.js y los módulos de marionetas pueden coexistir. Las siguientes son las ventajas.

  • Organización mucho más clara del código fuente y una separación más clara de las preocupaciones.
  • Los métodos de inicio y parada del módulo proporcionan la provisión para inicializar y limpiar objetos.
  • Cuando modela funcionalidades y subfunciones como módulos y submódulos, tenemos un control más granular sobre lo que reside en la memoria y lo que no debería.
  • Además, la definición del módulo se puede dividir en varios archivos.

Por favor, publique sus ideas. Gracias por leer.

PS: Con base en lo anterior punto de vista, por favor, encontrar los cambios en el siguiente ejemplo:

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