[marionetteJS](http://www.ituring.com.cn/article/31580)是在backboneJS基礎上進行更簡潔的操作,平常開發主要用到幾個涉及到view的概念:CollectionView、CompositeView、ItemView、LayoutView。這幾個概念中,用的最廣的當屬ItemView。ItemView相對于backbone中view的概念方便之處在于:不用顯式定義render方法,而是由ItemView本身完成將數據渲染到模板,并將視圖追加到el,由此可見減少了很多流程化的操作。
同時marionetteJS還有很多事件和回調方法如:onBeforeRender、onRender、onBeforeDestroy、onDestroy、onShow等。這些回調函數,都在相應事前執行前或后,被調用執行,即幫助開發人員設定好了時序的通用方法,大大簡化了業務邏輯實現。
當然本文并不是詳細講述[marionetteJS](http://marionettejs.com/docs/current)的原理,而是針對使用marionetteJS實現todoMVC功能([點擊下載](http://download.csdn.net/detail/yingyiledi/8050447))做講解。由于公司根據具體業務需要,在marionetteJS上又進行了一些封裝實現,不過基本功能marionetteJS沒有太大出入,故如看到代碼中Italent無需驚慌,只需做到理念上的理解即可。
**首先讓我們看一下,項目目錄、view目錄及templates目錄:**



**從以上三個目錄來看,相對于上一篇文章采用[backbone實現todoMVC](http://blog.csdn.net/yingyiledi/article/details/39994145)似乎沒有太大差別,那么差別在哪呢?**
**上篇文章中提到每個view所提供的職能:**
- **設置el或tagname,用于定義在上一層view放置的位置,或包裹的標簽**
- **設置對應模板(Template)**
- **定義交互事件,并連帶定義交互函數**
- **初始化函數(initialize),一般設置對collection或者model的監聽,用于view之間的通信**
- **渲染函數(render),用于渲染數據到模板中,設置其他一些全局函數**
?**在marionetteJS中,各種view所實現的職能與上述職能類似,不同之處在于上文講到內建Render及各執行時序上的回調,大大簡化了開發。除此之外各原子視圖并沒有太大的變動。**
**這里著重講解的是appView:**
~~~
Talent.Layout.extend({
//layout采用region
model: new Talent.Model(),
template: jst['about/app-page'],
initialize: function() {
this.collection = new Todos([{
title: 'ada'
}, {
title: 'oman'
}, {
title: 'come'
}]); //初始化collection便于調試
this.listenTo(this.collection, "add", this.addOne);
this.listenTo(this.collection, "all", this.reDraw); // 監聽collection的變化,執行添加和重繪
}, //這里的重繪中,用于調整部分內容顯示或隱藏的邏輯
regionsClass: {
input: InputView,
list: TodoView,
toggleAll: ToggleAllView,
status: StatusView
}, // 這里采用的regionsclass簡寫類
regions: {
// main: '.page-main-region'
todoApp: '#todo-header',
ToggleAll: '#todo-toggleAll',
status: "#todo-footer"
// todoList: '#todo-list'
}, // regions部分簡寫元素部分
ui: {
// item: '.ui-item'
},
events: function() {
var events = {};
// events['click ' + this.ui.item] = 'eventHandler';
return events;
},
onRender: function() {
},
onShow: function() {
var self=this;
this.todoApp.show(new this.regionsClass.input({
collection: this.collection
}));
this.ToggleAll.show(new this.regionsClass.toggleAll({
collection: this.collection
}));
this.addAll(); //已經渲染完再顯示,用于顯示所有初始化數據
this.addStatus();
if (this.collection.length) {
$("#main").show();
}; //這里用于初始化顯示collection數據
}, // onshow用于app模板顯示完,使用的邏輯。
reDraw: function() {
if(this.collection.length==0){
this.flag = true;
}
if((this.collection.length>=1)&&this.flag)
{
this.addStatus();
this.flag = false;
}//通過設置一個flag屬性,標記當collection從空到有值,再重新show statusview過程
if (this.collection.length) {
//渲染時執行顯示或隱藏的代碼
$("#main").show();
//如果collection為空的話,則清空footer
} else {
$("#main").hide();
}
}, //時刻監聽collection變化,顯示或隱藏部分region
addStatus:function(){
var statusView = new this.regionsClass.status({
collection: this.collection,
model: new Talent.Model({
done: this.collection.done().length,
remaining: this.collection.remaining().length,
length:this.collection.length
})
});
this.status.show(statusView);
},//添加狀態欄視圖
addOne: function(todo) {
var listItem = new this.regionsClass.list({
model: todo
});
listItem.render();
$("#todo-list").append(listItem.$el);
//這里不斷加入新的項并渲染加入到appview中
},
addAll: function() {
var self = this;
_.each(self.collection.models, function(item) {
self.addOne(item); //對collection每個都進行添加到appview頁面中顯示
})
}
});
});
~~~
appView采用的是layout類,layout混合了ItemView及Region概念,非常適合管理多個子視圖。appView下面有多個視圖,采用layout非常合適。
**layout有幾個概念:**
~~~
regionsClass: {
input: InputView,
list: TodoView,
toggleAll: ToggleAllView,
status: StatusView
}, // 這里采用的regionsclass簡寫類
regions: {
// main: '.page-main-region'
todoApp: '#todo-header',
ToggleAll: '#todo-toggleAll',
status: "#todo-footer"
// todoList: '#todo-list'
}, // regions部分簡寫元素部分
~~~
**regionsClass屬性可以給引入的類設置別名,regions屬性則是對所要插入的區域節點設置別名。**
**當需要將子視圖插入到appView視圖指定區域時,執行如下代碼:**
~~~
this.todoApp.show(new this.regionsClass.input({
collection: this.collection
}));
~~~
這里,show方法起到的作用,是將子視圖渲染并將el放到regions定義的區域節點下,則子視圖被展示到appView指定區域。
上面提到marionetteJS各類視圖都內建了render,那么之前采用backboneJS監聽collection或者model變化所執行的this.render就受到了限制,因為除了將數據塞入模板及放到el下,我們可能還需要其他的邏輯連同執行。
**樂帝這里采用了一個自定義方法,并做事件監聽。**
~~~
reDraw: function() {
if(this.collection.length==0){
this.flag = true;
}
if((this.collection.length>=1)&&this.flag)
{
this.addStatus();
this.flag = false;
}//通過設置一個flag屬性,標記當collection從空到有值,再重新show statusview過程
if (this.collection.length) {
//渲染時執行顯示或隱藏的代碼
$("#main").show();
//如果collection為空的話,則清空footer
} else {
$("#main").hide();
}
}, //時刻監聽collection變化,顯示或隱藏部分region
~~~
**事件監聽:**
~~~
this.listenTo(this.collection, "all", this.reDraw); // 監聽collection的變化,執行添加和重繪
~~~
**為了使程序更加標準,這里采用了新型的隱藏或展示視圖的方式,涉及到status子視圖的隱藏和展示。按照Jquery式編程,通過選取指定dom元素,采取show及hide方法,即可解決。**
**這里為了充分發揮數據驅動執行方式,在statusView視圖中,當collection中model長度為零時,關閉視圖:**
~~~
reDraw: function() {
if(this.collection.length==0){
this.close();
}
var length = this.collection.length;
this.model.set({
done: this.collection.done().length,
remaining: this.collection.remaining().length,
length:this.collection.length
});
this.render();
}
~~~
**此時,視圖關閉后,整個視圖在dom及內存中被移除,當collection中model再次非零時,需要重啟視圖,就需要在appView里,重新show一個statusView。**
**這里定義了一個添加statusView方法:**
~~~
addStatus:function(){
var statusView = new this.regionsClass.status({
collection: this.collection,
model: new Talent.Model({
done: this.collection.done().length,
remaining: this.collection.remaining().length,
length:this.collection.length
})
});
this.status.show(statusView);
},//添加狀態欄視圖
~~~
**再將如上方法,在自定義監聽collection變化的回調函數中引入即可:**
~~~
reDraw: function() {
if(this.collection.length==0){
this.flag = true;
}
if((this.collection.length>=1)&&this.flag)
{
this.addStatus();
this.flag = false;
}//通過設置一個flag屬性,標記當collection從空到有值,再重新show statusview過程
if (this.collection.length) {
//渲染時執行顯示或隱藏的代碼
$("#main").show();
//如果collection為空的話,則清空footer
} else {
$("#main").hide();
}
}, //時刻監聽collection變化,顯示或隱藏部分region
~~~
**注意這里設置了一個標志屬性flag,用于記錄collection是從空到增加model,這種狀態才重新開啟statusView子視圖。**
**至此,涉及到有關此篇采用marionetteJS實現todoMVC的關鍵問題,都已經做了闡述。**
**與backbone相比,更多的規則,帶來的是更少的代碼,采用任何技術都是在學習成本與高效開發上做權衡。**
****
- 前言
- 前端編程提高之旅(一)----插件
- 前端編程提高之旅(二)----網站常見特效的jquery實現
- 前端編程提高之旅(三)----瀏覽器兼容之IE6
- 前端編程提高之旅(四)----backbone初體驗
- 前端編程提高之旅(五)----寫給大家看的css書
- 前端編程提高之旅(六)----backbone實現todoMVC
- 前端編程提高之旅(七)----marionette實現todoMVC
- 前端編程提高之旅(八)----D3.js數據可視化data join解析
- 前端編程提高之旅(九)----延遲對象
- 前端編程提高之旅(十)----表單驗證插件與cookie插件
- 前端編程提高之旅(十一)----jquery代碼的組織
- 前端編程提高之旅(十二)----position置入值應用
- 前端編程提高之旅(十三)----jquery選擇器
- 前端編程提高之旅(十四)----jquery DOM操作
- 前端編程提高之旅(十五)----jquery事件
- 前端編程提高之旅(十六)----jquery中的動畫
- 前端編程提高之旅(十七)----jquery中表單、表格和ajax
- 前端編程提高之旅(十八)----移動端web流行交互技術方案研究