使用 Backbone.Marionette 管理複雜 UI 交互

只扯蛋,不給代碼,就是耍流氓 -- 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              |
        |<--------------------------|         |<--------------------------------|

其中涉及的問題有:學習

  1. 業務邏輯: model 和 collection 處理大部分邏輯。他們對應着服務端後臺的資源,也對應着視圖顯示的類容。

  2. 構建 DOM:通常是 handlebars。

  3. 視圖邏輯:Backbone.View ,其中的邏輯要本身維護。

  4. 視圖和模型同步: 本身維護。

  5. 管理複雜的 UI 交互:本身維護。

  6. 管理狀態和路由:Backbone.Router(不支持管理視圖和應用狀態)

  7. 建立與鏈接組件: 手動實現。


管理複雜的 UI 交互

那麼,這篇文章着重於講 UI 交互,全部的 UI 交互均可以被劃分爲:

  1. 簡單交互:使用觀察者同步(Observer Synchronization),被動控制顯示,操做 DOM 事件來改變集合模型,視圖監聽集合模型的變化來改變自身。Backbone.View 就是這樣工做的。

  2. 複雜交互:使用流同步(Flow Synchronization),主動控制顯示 SUPERVISING PRESENTERS

使用 Marionette 工做流程是這樣的:

events for
                     complex interactions                                  notice
Template/DOM (View) ----------------------> Marionette.View (Presenter) ------------> Backbone.Model (Model)
        |                                           |        |                                |
        |               complex updates             |        |             events             |
        |<------------------------------------------|        |<-------------------------------|
                                                             |                                |
                                                             |        simple updates          |
                                                             |------------------------------->|

視圖 View & 區域 Region

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 的。


LayoutView

佈局視圖,好比你的界面上可能用 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());

ItemView 與 CompositeView

單條記錄 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)


Event Aggregator

事件聚合器,這個東西主要是用來解耦的,例如:從 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 中維護的。


以上總結

  1. Marionette.View 在 Backbone.View 之上多作了不少事情,包括自動渲染和重繪等等。

  2. Marionette.View 接到 Dom 事件後,能夠通知 notice 集合 Collection 去處理。也能夠直接命令 commands 模型 Model 去處理。

(這裏只介紹了一些入門知識 Marionette 未完待續...)

mn

相關文章
相關標籤/搜索