只扯蛋,不給代碼,就是耍流氓 -- honger。html
完整的 tutorial 代碼 戳這裏, 由於我使用的是 commonjs 規範,基於 spm 的,你能夠先安裝,而後運行它。更多 spm 資料git
// 安裝 npm install spm -g // 運行 spm server
這個 repo 是我學習各類技術棧的一個集合,若是是初學者,能夠跟我一塊兒來學習,也能夠私信我。github
你也能夠 find me on GitHubnpm
Backbone.Marionette 的中文資料真是少之又少,所以這篇會盡可能介紹的較爲詳細。編程
不少人抱怨和吐槽 Backbone
, 以爲它太簡單了。什麼事都要本身作。然而,Backbone 的優勢也是它太簡單了,它的思想就是不做任何綁定, 只提供一個骨架。正如 Backbone 的中文意思。bash
因此大量的問題都留給開發者本身想辦法來解決,所以遭到吐槽...dom
固然,使用純 Backbone 開發一個複雜應用時,狀況就會變得很是糟糕。佈局
純 Backbone 的工做流程是這樣的: MVPpost
events commands Template/DOM (View) ----------> Backbone.View (Presenter) ----------> Backbone.Model (Model) | | | | | updates | | events | |<--------------------------| |<--------------------------------|
其中涉及的問題有:學習
業務邏輯
: model 和 collection 處理大部分邏輯。他們對應着服務端後臺的資源,也對應着視圖顯示的類容。
構建 DOM
:通常是 handlebars。
視圖邏輯
:Backbone.View ,其中的邏輯要本身維護。
視圖和模型同步
: 本身維護。
管理複雜的 UI 交互
:本身維護。
管理狀態和路由
:Backbone.Router(不支持管理視圖和應用狀態)
建立與鏈接組件
: 手動實現。
那麼,這篇文章着重於講 UI 交互,全部的 UI 交互均可以被劃分爲:
簡單交互
:使用觀察者同步(Observer Synchronization),被動控制顯示,操做 DOM 事件來改變集合模型,視圖監聽集合模型的變化來改變自身。Backbone.View 就是這樣工做的。
複雜交互
:使用流同步(Flow Synchronization),主動控制顯示 SUPERVISING PRESENTERS
使用 Marionette 工做流程是這樣的:
events for complex interactions notice Template/DOM (View) ----------------------> Marionette.View (Presenter) ------------> Backbone.Model (Model) | | | | | complex updates | | events | |<------------------------------------------| |<-------------------------------| | | | simple updates | |------------------------------->|
Marionette 擴展了很是豐富的視圖 View 組件:ItemView
CollectionView
CompositeView
LayoutView
.
不只於此,Marionette 還使用 Region (區域)來配合 View (視圖)。
通常會先添加一個 Region 來定位一塊地方,再決定這塊地方顯示哪一個 View 。
// 你能夠理解爲一箇中心 APP 對象。當一切準備就緒的時候,調用 App.start(options) 啓動應用。 var MyApp = new Backbone.Marionette.Application(); // 添加一個 region,它對應一個 dom 節點 App.addRegions({ mainRegion: '#content' }); // 讓這個 region 顯示一個視圖, 這個視圖會當即渲染 App.mainRegion.show(new MyView());
從頭提及吧,你可能注意到了,上面實例化了一個 Marionette.Application 對象。
一般須要定義一個 App ,經過 Initializers 把全部的事都綁定在上面。等待 start 方法調用的時候,開始執行。
// start 方法調用後,當即執行 Initializers MyApp.addInitializer(function(options) { // 實例化 compositeView var angryCatsView = new AngryCatsView({ collection: options.cats }); // 顯示這個視圖 MyApp.mainRegion.show(angryCatsView); }) MyApp.start({cats: cats});
這裏只綁定了一個 Initializer,在一個複雜的應用中,你可能會綁定多個的。start(options) 中的參數 options 會傳遞個每一個 Initializer。
經過擴展 Backbone.Events, 實現 Aspect(切面編程) 你能夠監聽這些事件,讓應用更加靈活。
以前分析過 Arale 的 Events 代碼,如今的 Backbone.Events 就是從 Arale 的 Events 合併過來的,看個人 gitbook
App.on('initialize:before', function(options) { // doSomething... }); App.on('initialize:after', function(options) { // doOtherthing... }); App.on('start', function(options) { Backbone.history.start(); });
好了,如今已經知道了 Marionette 是怎麼啓動的了,下一步是瞭解它是怎麼管理視圖 View 的。
佈局視圖,好比你的界面上可能用 header main footer 等區域。
<div id="content"> <div id="header"></div> <div id="main"></div> <div id="footer"></div> </div>
你能夠這樣來定義佈局視圖,這樣你就掌控全局了。
var RootLayout = Backbone.Marionette.LayoutView.extend({ el: '#content', regions: { header: '#header', main: '#main', footer: '#footer' } })
通常會把這個 root 掛載到 App 上。
var MyApp = Backbone.Marionette.Application.extend({ setRootLayout: function () { this.root = new RootLayout(); } }); // App 啓動前,實例化它,獲得 App.root MyApp.on('before:start', function () { MyApp.setRootLayout(); });
如今 App 上有了 root 的控制權了,能夠任意設置某個區域顯示某個視圖了。
MyApp.root.showChildView('header', new HeaderLayout());
單條記錄 Model 對應 ItemView, CompositeView 不只對應的是一個包含 ItemView ,還對應有其餘一些相關視圖.
他們一般在一塊兒使用,而且 ItemView 是 CompositeView 的 childView 屬性值。
好比這樣兩個 template
<!-- CompositeView 模板 --> <thead> <tr><th>Name</th></tr> </thead> <tbody> </tbody> <!-- ItemView 模板 --> <tr><td>{{name}}</td></tr>
我須要在 tbody 標籤下加入多個 ItemView。這樣你就須要使用 childViewContainer 來指定 childView 被加在什麼地方。
很顯然此處: {childViewContainer: 'tbody'}
.
這裏是以上代碼
var AngryCatView = Backbone.Marionette.ItemView.extend({ template: require('./tpl/angrycat.handlebars'), tagName: 'tr', className: 'angry_cat' }); var AngryCatsView = Backbone.Marionette.CompositeView.extend({ tagName: 'table', id: 'angry_cats', className: 'table-striped table-bordered', template: require('./tpl/angrycats.handlebars'), childView: AngryCatView, childViewContainer: 'tbody' })
細心的童鞋應該已經注意到了,模板中爲何不用 table 標籤包裹起來。這是由於 Marionette 會爲你包裹一層,若你不指定 tagName
則默認是 div 標籤。 指定的 className
, id
屬性也是加在這層上面的。
純 Backbone 代碼須要本身來實現 render 渲染 DOM,在這裏 Marionette 經過指定的 template 屬性自動渲染了。
重點 在 這一層 咱們要作的是監聽 Model,Collection 的變化,來同步視圖。和 Backbone 作法同樣。不一樣的是,Marionette 能夠指定是所有重繪(render)仍是部分重繪(renderCollection)
事件聚合器,這個東西主要是用來解耦的,例如:從 ItemView 上來個事件,改變了 model 的屬性。影響了集合的排列。須要更新到 CompositeView 上。
在 ItemView 中調用 CompositeView ? 這樣作是不對的,由於會讓應用愈來愈複雜的。視圖 View 也不該該去處理 business logic。
使用 Event Aggregator 會讓程序解耦,它至關於一種 Publish/Subscribe 模式。視圖只須要去通知 notice 模型 Model or Collection 來處理。
MyApp.trigger('rank:up', this.model);
在模型 Model or Collection 初始化的時候就要 Subscribe 訂閱事件 rank:up
MyApp.on('rank:up', function(cat) { if (cat.get('rank') === 1) { return true; } self.rankUp(cat); self.sort(); })
這樣的話,business logic 就是在 Model or Collection 中維護的。
Marionette.View 在 Backbone.View 之上多作了不少事情,包括自動渲染和重繪等等。
Marionette.View 接到 Dom 事件後,能夠通知 notice 集合 Collection 去處理。也能夠直接命令 commands 模型 Model 去處理。
(這裏只介紹了一些入門知識 Marionette 未完待續...)