Marionette牽線木偶,Backbone是脊骨的意思,Marionette是基於Backbone作擴展庫,能夠理解爲把脊骨骨架綁線扯着變成牽線木偶動起來哈哈,使backbone更易使用呵呵!css
構建或者擴展了不少新的東西,如:Application,Region,ItemView,CollectionView,CompositeView,LayoutView,AppRoute,Controller等等,把不少重複性的工做變成配置,程序入口引入了集中處理器Application,貌似Marionette的module不怎麼好用,還不如用requireJS來得直觀。html
比較清晰,bower_components裏面存放jQuery,underscore等等依賴js庫及js框架,不用管它;css文件也不用理它。html5
一,主程序(/index.html-> js/main.js-> js/app.js ->js/routers/index.js & js/controllers/index.js)jquery
/index.htmlgit
<!doctype html>
<html lang="en" data-framework="marionettejs">
<head>
<meta charset="utf-8">
<title>Backbone.Marionette & Requirejs • TodoMVC</title>
<link rel="stylesheet" href="bower_components/todomvc-common/base.css">
<link rel="stylesheet" href="css/custom.css">
</head>
<body>
<section id="todoapp">
<header id="header">
</header>
<section id="main">
</section>
<footer id="footer">
</footer>
</section>
<footer id="info">
<p>Double-click to edit a todo</p>
<p>Created by <a href="http://github.com/jsoverson">Jarrod Overson</a></p>
</footer>
<script src="bower_components/todomvc-common/base.js"></script>
<script data-main="js/main" src="bower_components/requirejs/require.js"></script><!--requireJS開始加載js/main.js文件-->
</body>
js/main.jsgithub
require.config({//requireJS配置
paths: {//路徑配置
underscore: '../bower_components/underscore/underscore', backbone: '../bower_components/backbone/backbone', marionette: '../bower_components/backbone.marionette/lib/backbone.marionette', jquery: '../bower_components/jquery/jquery', localStorage: '../bower_components/backbone.localStorage/backbone.localStorage', tpl: 'lib/tpl' }, shim: {//非AMD規範庫如backbone等庫的配置,deps是依賴庫,The shim config allows us to configure dependencies for scripts that do not call define() to register a module即下面的庫不是經過define()來註冊成爲模塊的
underscore: { exports: '_' }, backbone: { exports: 'Backbone', deps: ['jquery', 'underscore'] }, marionette: { exports: 'Backbone.Marionette', deps: ['backbone'] } }, deps: ['jquery', 'underscore'] }); require([ 'app', 'backbone', 'routers/index', 'controllers/index' ], function (app, Backbone, Router, Controller) { //requireJS標準寫法 'use strict'; app.start();//應用啓動-〉app.js
new Router({ controller: Controller });//指定了Controller(controllers/index)的Marionette.AppRouter(routers/index;監視url傳值觸發相應的事件
Backbone.history.start();//當你的全部路由建立而且設置完畢後,調用Backbone.history.start()來開始記錄url的hash change,若是是html5還能夠記錄pushState等
});
js/app.jsmvc
/*global define */ define([ 'marionette', 'collections/TodoList', 'views/Header', 'views/TodoListCompositeView', 'views/Footer' ], function (Marionette, TodoList, Header, TodoListCompositeView, Footer) {//requireJS標準寫法,其實就是用function裏的變量去表示相應的庫/模塊的返回值(注意:根據requireJS規範,每一個模塊應該要有返回值,如app.js最後用了return window.app=app;)
'use strict'; var app = new Marionette.Application(); //建立APP, Marionette官方描述爲:the hub of your composite //application. It organizes, initializes and coordinates the various pieces of your app.
var todoList = new TodoList();//collections/TodoList, collections就是model集
var viewOptions = { collection: todoList }; var header = new Header(viewOptions); var main = new TodoListCompositeView(viewOptions); var footer = new Footer(viewOptions);//這三個view都是綁定collections/TodoList這個collection
app.addRegions({//給app增長region,region是分區處理更加靈活
header: '#header', main: '#main', footer: '#footer' }); app.addInitializer(function () {//添加事件到Marionette的初始器 app啓動時會被立刻執行 //show 三個region
app.header.show(header); app.main.show(main); app.footer.show(footer); todoList.fetch();//collection todoList獲取localstorage的數據
}); app.listenTo(todoList, 'all', function () {//監聽collection todoList 全部事件包括todoList.fetch();
app.main.$el.toggle(todoList.length > 0);//main view執行toggle 函數
app.footer.$el.toggle(todoList.length > 0);//footer view執行toggle 函數
}); app.vent.on('todoList:filter', function (filter) {//vent是用於定義供實例外部引用的函數,能夠看見在controller裏面trigger此函數
footer.updateFilterSelection(filter);//執行footer view裏面的函數
document.getElementById('todoapp').className = 'filter-' + (filter === '' ? 'all' : filter);//純js
}); app.vent.on('todoList:clear:completed', function () {//vent是用於定義供實例外部引用的函數,能夠看見在footer view裏面trigger此函數
todoList.getCompleted().forEach(function (todo) { todo.destroy(); }); }); return window.app = app;//把app綁到window全局對象並返回
});
js/routers/index.jsapp
/*global define */ define([ 'marionette' ], function (Marionette) { 'use strict'; return Marionette.AppRouter.extend({ appRoutes: { '*filter': 'setFilter'//*splat表示能夠匹配任意數量的URL形式,如路由:file/*path -> file/a/b/c.txt,傳遞值爲/a/b/c.txt;題外的如 :param將匹配斜槓/之間單一的一個URL變量,如路由:search/:query/p:page -> #search/obama/p2,傳值爲"obama"和"2"
} }); });
js/controllers/index.js框架
/*global define */ define([ 'app' ], function (app) { 'use strict'; return { setFilter: function (param) { app.vent.trigger('todoList:filter', param && param.trim() || '');//根據URL中的傳的值param觸發app.js中定義的vent(todoList:filter)的函數
} }; });