私見をモジュールフォーマット "
私は、Require.jsモジュールとMarionette.jsモジュールをC#のアセンブリと名前空間の概念で比較したいと思います。 Marionette.jsのモジュールは、機能に基づいてさまざまなビルディングブロックの定義をグループ化するのに役立ちますが、Require.jsを使用して依存関係をロード/注入することができます。
これは私の実装に役立ったDavid Sulc氏の書籍「RequireJSと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;
});
});
は理にかなっています。ありがとう!私は、私がBBCloneMailのような頭のスクリプトタグにすべてのアプリケーションファイルを貼り付けなければならない、マリオネットモジュールを使用したと仮定しているので、RequireJSを使用するつもりです。 –
複数のスクリプトタグを使用することはお勧めしません。 BBCloneMailはそのようなことを行う例ではありません。 :)実際のプロジェクトでは、連結して縮小するビルドステップがあります。 r.jsはrequirejsモジュールのために行うか、Railsのアセットパイプラインやgrunt.jsや他の多くのツールのような多くのツールで行うことができます。 –
ここに、RequireJSでMarionetteを使用するための更新リンクがあります。 (githubリポジトリが移動しました)https://github.com/marionettejs/backbone.marionette/wiki/Using-marionette-with-requirejs –