javascript - libreria - Backbone Marionette y RequireJS Modules
underscore empty object (2)
En mi humilde opinión, me gusta diferir del punto de vista mencionado anteriormente "Los módulos de Marionette están destinados a ser una alternativa simple a los módulos RequireJS (y otros)".
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 nombres de C #. Los módulos de Marionette.js nos ayudan a agrupar definiciones de varios bloques de construcción basados en la funcionalidad, mientras que Require.js podría usarse para cargar / inyectar dependencias.
Una vez más, este es mi punto de vista / comprensión (basado en las discusiones con David Sulc en su libro ''Estructuración de código de red troncal con módulos RequireJS y Marionette''), que me ha ayudado en mi implementación. De una manera podemos usar Marionette.js y Require.js juntos como se describe a continuación.
El siguiente ejemplo es una pequeña aplicación de Library Manager (ejemplo) que se puede encontrar en línea en https://github.com/srihari-sridharan/LibraryManagement . El código a continuación (omitiendo bits y partes insignificantes) crea el objeto de la aplicación y presenta la lista de libros después de la inicialización. Puede encontrarlo 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 definimos el módulo / submódulos en función de la funcionalidad. Esto también tendrá un enrutador específico para el módulo y se conectarán los controladores y se manejarán las rutas. Tenga en cuenta la necesidad de llamar 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;
});
Finalmente tenemos las definiciones de nuestros puntos de vista, modelos y controladores. Estas definiciones estarán vinculadas a los objetos de módulo / submódulo.
El código de vista se muestra a continuación. Mira los métodos .extend (). Se asignan a 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.
});
Así, los módulos require.js y los módulos de marionetas pueden coexistir. Las siguientes son las ventajas.
- Organización mucho más limpia 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 una provisión para inicializar y limpiar objetos.
- Cuando modela funcionalidades y sub-funcionalidades 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 pensamientos. Gracias por leer.
PD: basado en el punto de vista anterior, encuentre los cambios en su ejemplo a continuación:
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;
});
});
Estoy empezando una aplicación javascript a gran escala con Marionette. Una aplicación de Marionette tiene un concepto de módulos de aplicación y RequireJS también se utiliza para dividir el código en módulos,
Actualmente tengo esto para el inicio de mi aplicación:
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 agregar una vista, ¿haría 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 funcionaría este código, cualquier ayuda es muy apreciada.
Los módulos de Marionette están destinados a ser una alternativa simple a los formatos de módulos RequireJS (y otros). No recomendaría usarlos juntos, como se señala en la wiki:
https://github.com/marionettejs/backbone.marionette/wiki/AMD-Modules-vs-Marionette''s-Modules