導讀
最近一段時間,我在研究移動WebApp應用開發,想在設計WebApp前端JS構架時,使用MVC分層技術,經過一段時間的技術選型,最終確定使用 Backbone JS 作為底層基礎MVC框架。在使用Backbone寫示例時,總是覺得非常怪,但又說不出怪在哪,所以,就想通過Backbone與Ext JS 4 MVC的對比,來發現Backbone的缺點與優化點。PS:由于我在做Desktop前端JS開發時,十分青睞Ext JS這一類的框架,Ext JS 4 MVC是我認為在所有框架中做得最好的。
?
特性對比
在對比兩個MVC框架之前,必須理解四個十分重要的特性:
- UI Bindings:[UI 綁定] 我想說的不僅僅是模板,而是想談一種在底層模型出現變化時,視圖層能夠自動刷新的方法。一旦您用過了支持 UI Binding 的框架(例如Ext)就很難放手回頭了。
- Composed Views:[組件化視圖] 與所有的軟件開發者一樣,我也喜歡編寫模塊化、可重用的代碼。基于這樣的原因,當給 UI 編程的時候,我喜歡使用視圖的方法來開發(個人更偏好在模板層時使用),當然這樣也就需要擁有足夠豐富的視圖組件來支持。
- Web Presentation Layer:[web 表示層] 我們在編寫 web 程序時想要 Native 風格的組件,但是也沒有理由來為一個 web 框架來創建它自己的布局管理器。HTML 和 CSS 是目前解決樣式與布局的最好的方法,框架也應該以這一點為核心。
- Play Nicely With Others:[兼容,友好] 不得不承認jQuery是十分犀利的。我不喜歡那種綁定著一個定制的jQuery副本的框架,而推薦直接使用jQuery。
下面是兩個框架對于四種特性支持程度的對比
?
實例對比
咱們先看一個簡單的小例子,分別使用Ext JS與Backbone實現。這個例子也是Ext JS 4官方源碼中的一個例子,參見
http://dev.sencha.com/deploy/ext-4.1.0-gpl/examples/app/simple/simple.html
對Ext JS 4 MVC不熟悉的同學,可以閱讀文章
ExtJS 4 MVC架構講解
,這篇文章對Ext JS 4 MVC講解得很透徹。
?
Ext JS 4 MVC例子
1、目錄結構。
2、定義Application。你可以把app當作是一個應用入口,app包含應用的全局配置,同時也負責維護模型、視圖、控制器的引用。Ext.app.Application本身也是繼承自Ext.app.Controller,具體參見源碼與官方文檔。
Ext.application({
name: 'AM',
// automatically create an instance of AM.view.Viewport
autoCreateViewport: true,
controllers: [
'Users'
]
});?
3、定義Viewport。Viewport中定義了app被加載時的初始視圖。
Ext.define('AM.view.Viewport', {
extend: 'Ext.container.Viewport',
layout: 'fit',
items: [{
xtype: 'userlist'
}]
});
?
4、定義控制器。Controller是Model與View的粘合劑,Controller的control()函數使用ComponentQuery表達式設置組件視圖的事件監聽,這樣就很好的將視圖的控制邏輯與View本身分離,達到View重用的目的,當View是由組件構成時,組件的重用就顯得很重要。不熟悉ComponentQuery請參見官方文檔。
Ext.define('AM.controller.Users', {
extend: 'Ext.app.Controller',
stores: ['Users'],
models: ['User'],
views: ['user.Edit', 'user.List'],
refs: [
{
ref: 'usersPanel',
selector: 'panel'
}
],
init: function() {
this.control({
'viewport > userlist dataview': {
itemdblclick: this.editUser
},
'useredit button[action=save]': {
click: this.updateUser
}
});
},
editUser: function(grid, record) {
var edit = Ext.create('AM.view.user.Edit').show();
edit.down('form').loadRecord(record);
},
updateUser: function(button) {
var win = button.up('window'),
form = win.down('form'),
record = form.getRecord(),
values = form.getValues();
record.set(values);
win.close();
this.getUsersStore().sync();
}
});
?
5、Model和View。在此略過代碼部分,對于不熟悉Ext的同學,參見官方的源碼及例子。Ext JS的Model、Store和View實現了UI Binding,當Model數據發生變化時自動完成View刷新。在上面的例子中,有一行代碼
record.set(values);
,Record就是一個Model實例,當record被賦值時視圖被刷新,這部分代碼在
ExtJS 4 MVC架構講解
文中有詳細描述。
?
Backbone MVC例子
1、定義Model。Backbone的Model與Ext Model差不多,但是,Ext Model支持對象依賴關聯,這個在特性復雜的企業應用中會比較有用,文章末尾會詳細的解釋對象依賴關聯。Collection與Ext Store在概念上相似,但是,Collection僅僅是一個集合,而Store則是Ext非常重要的一個功能,它是Ext實現數據交互的重要中間件,功能非常強大,有興趣的同學可以翻閱官方文檔。
var User = Backbone.Model.extend({
idAttribute: 'id',
url: '../testdata'
});
var uer = new User();
var UserList = Backbone.Collection.extend({
url: '../testdata',
model: User
});
var users = new UserList();
?
2、定義View。Backbone的View可以結合JS模版引擎實現視圖渲染,視圖事件控制使用事件委托的方式,例子中,el對象綁定一個委托click事件,當點擊tr時調用函數showProfile,具體View事件請參見Backbone官方源碼。視圖控制事件監聽應該出現在Controller中,由于Backbone沒有Controller的概念,所以視圖控制事件監聽在View中實現,與視圖渲染混在一起,導致視圖無法重用,沒有達到MVC分層的目的。現在,我們換一種思路思考,把Backbone View看作是一個Controller,View僅僅使用是一個HTML模版,雖然有點牽強,但視乎也是MVC。Backbone在早期的版本是有Controller這個類,但在新版本將Controller重命名成Router,我想Backbone作者也意識到了這個問題的存在吧!
var HomeView = Backbone.View.extend({
el: $('#mainview'),
events: {
'click tr': 'showProfile'
},
showList: function() {
var html = ['<table>'];
users.each(function(uer) {
html.push('<tr>');
html.push('<td>', uer.get('firstname'), '</td>');
html.push('<td>', uer.get('lastname'), '</td>');
html.push('</tr>');
});
html.push('</table>');
this.$el.html(html.join(''));
},
showProfile: function() {
this.$el.html('Hello, ' + uer.get('firstname') + ' ' + uer.get('lastname'));
}
});
var home = new HomeView();
?
3、定義Router。Router是個好東西,可以監聽地址欄hash改變,實現頁面跳轉的控制邏輯。這視乎和Controller有點關系,但又能不說Router是Controller,這也是Controller重命名成Router的一個原因。
var AppRouter = Backbone.Router.extend({
routes: {
'list': 'list',
'profile/:id': 'getProfile'
},
getProfile: function(id) {
uer.set('id', id);
uer.fetch({
type: 'POST',
data: {
id: id
},
success: function() {
home.showProfile();
}
});
},
list: function() {
users.fetch({
type: 'POST',
success: function() {
home.showList();
}
});
}
});
new AppRouter();
Backbone.history.start();
?
總結
Ext JS 4 MVC是我認為非常完美的MVC框架之一,但是太依賴Ext的體系,很難從體系中剝離出來。
Backbone JS優點、缺點都比較明顯:
- 優點:小巧、輕便可以很容易的集成到應用中,Backbone MVC可以適用大部分的項目需求。
- 缺點:Backbone是MVC的不完整實現,只實現了部分,功能比較弱。
我會考慮增加一些Backbone的功能,如Collection和Model的離線緩存,UI綁定數據改變自動渲染,在業務層封裝出類似Ext的MVC,模版與組件化是視圖渲染的兩種主要方式。
?
擴展閱讀------對象依賴關聯
一個Model對象與其他Model對象存在依賴關系。定義兩個Model:User、Post,User與Post的關系是一對多。
服務端響應JSON格式:
{
id: 'user1',
posts: [{
id: 'post1',
user_id: 'user1',
}, {
id: 'post2',
user_id: 'user1',
}, {
id: 'post3',
user_id: 'user1',
}]
}
?
使用Ext JS 4定義Model:
Ext.define('Post', {
extend: 'Ext.data.Model',
fields: ['id', 'user_id'],
belongsTo: 'User'
});
Ext.define('User', {
extend: 'Ext.data.Model',
fields: ['id'],
hasMany: {model: 'Post', name: 'posts'}
});
?
數據訪問:
User.load('user1', {
success: function(user){
user.posts().each(function(rec){
console.log(rec.get('id'));
});
}
});
?
參考資料
- The Top 10 Javascript MVC Frameworks Reviewed
- Backbone JS框架指南
- Backbone源碼分析-Backbone架構+流程圖
- ExtJS 4 MVC架構講解
原創文章,轉載請注明出處 http://zhangdaiping.iteye.com
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元

