導(dǎo)讀
最近一段時間,我在研究移動WebApp應(yīng)用開發(fā),想在設(shè)計WebApp前端JS構(gòu)架時,使用MVC分層技術(shù),經(jīng)過一段時間的技術(shù)選型,最終確定使用 Backbone JS 作為底層基礎(chǔ)MVC框架。在使用Backbone寫示例時,總是覺得非常怪,但又說不出怪在哪,所以,就想通過Backbone與Ext JS 4 MVC的對比,來發(fā)現(xiàn)Backbone的缺點與優(yōu)化點。PS:由于我在做Desktop前端JS開發(fā)時,十分青睞Ext JS這一類的框架,Ext JS 4 MVC是我認為在所有框架中做得最好的。
?
特性對比
在對比兩個MVC框架之前,必須理解四個十分重要的特性:
- UI Bindings:[UI 綁定] 我想說的不僅僅是模板,而是想談一種在底層模型出現(xiàn)變化時,視圖層能夠自動刷新的方法。一旦您用過了支持 UI Binding 的框架(例如Ext)就很難放手回頭了。
- Composed Views:[組件化視圖] 與所有的軟件開發(fā)者一樣,我也喜歡編寫模塊化、可重用的代碼。基于這樣的原因,當給 UI 編程的時候,我喜歡使用視圖的方法來開發(fā)(個人更偏好在模板層時使用),當然這樣也就需要擁有足夠豐富的視圖組件來支持。
- Web Presentation Layer:[web 表示層] 我們在編寫 web 程序時想要 Native 風格的組件,但是也沒有理由來為一個 web 框架來創(chuàng)建它自己的布局管理器。HTML 和 CSS 是目前解決樣式與布局的最好的方法,框架也應(yīng)該以這一點為核心。
- Play Nicely With Others:[兼容,友好] 不得不承認jQuery是十分犀利的。我不喜歡那種綁定著一個定制的jQuery副本的框架,而推薦直接使用jQuery。
下面是兩個框架對于四種特性支持程度的對比
?
實例對比
咱們先看一個簡單的小例子,分別使用Ext JS與Backbone實現(xiàn)。這個例子也是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架構(gòu)講解
,這篇文章對Ext JS 4 MVC講解得很透徹。
?
Ext JS 4 MVC例子
1、目錄結(jié)構(gòu)。
2、定義Application。你可以把app當作是一個應(yīng)用入口,app包含應(yīng)用的全局配置,同時也負責維護模型、視圖、控制器的引用。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()函數(shù)使用ComponentQuery表達式設(shè)置組件視圖的事件監(jiān)聽,這樣就很好的將視圖的控制邏輯與View本身分離,達到View重用的目的,當View是由組件構(gòu)成時,組件的重用就顯得很重要。不熟悉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實現(xiàn)了UI Binding,當Model數(shù)據(jù)發(fā)生變化時自動完成View刷新。在上面的例子中,有一行代碼
record.set(values);
,Record就是一個Model實例,當record被賦值時視圖被刷新,這部分代碼在
ExtJS 4 MVC架構(gòu)講解
文中有詳細描述。
?
Backbone MVC例子
1、定義Model。Backbone的Model與Ext Model差不多,但是,Ext Model支持對象依賴關(guān)聯(lián),這個在特性復(fù)雜的企業(yè)應(yīng)用中會比較有用,文章末尾會詳細的解釋對象依賴關(guān)聯(lián)。Collection與Ext Store在概念上相似,但是,Collection僅僅是一個集合,而Store則是Ext非常重要的一個功能,它是Ext實現(xiàn)數(shù)據(jù)交互的重要中間件,功能非常強大,有興趣的同學可以翻閱官方文檔。
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可以結(jié)合JS模版引擎實現(xiàn)視圖渲染,視圖事件控制使用事件委托的方式,例子中,el對象綁定一個委托click事件,當點擊tr時調(diào)用函數(shù)showProfile,具體View事件請參見Backbone官方源碼。視圖控制事件監(jiān)聽應(yīng)該出現(xiàn)在Controller中,由于Backbone沒有Controller的概念,所以視圖控制事件監(jiān)聽在View中實現(xiàn),與視圖渲染混在一起,導(dǎo)致視圖無法重用,沒有達到MVC分層的目的。現(xiàn)在,我們換一種思路思考,把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是個好東西,可以監(jiān)聽地址欄hash改變,實現(xiàn)頁面跳轉(zhuǎn)的控制邏輯。這視乎和Controller有點關(guān)系,但又能不說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();
?
總結(jié)
Ext JS 4 MVC是我認為非常完美的MVC框架之一,但是太依賴Ext的體系,很難從體系中剝離出來。
Backbone JS優(yōu)點、缺點都比較明顯:
- 優(yōu)點:小巧、輕便可以很容易的集成到應(yīng)用中,Backbone MVC可以適用大部分的項目需求。
- 缺點:Backbone是MVC的不完整實現(xiàn),只實現(xiàn)了部分,功能比較弱。
我會考慮增加一些Backbone的功能,如Collection和Model的離線緩存,UI綁定數(shù)據(jù)改變自動渲染,在業(yè)務(wù)層封裝出類似Ext的MVC,模版與組件化是視圖渲染的兩種主要方式。
?
擴展閱讀------對象依賴關(guān)聯(lián)
一個Model對象與其他Model對象存在依賴關(guān)系。定義兩個Model:User、Post,User與Post的關(guān)系是一對多。
服務(wù)端響應(yīng)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'} });
?
數(shù)據(jù)訪問:
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架構(gòu)+流程圖
- ExtJS 4 MVC架構(gòu)講解
原創(chuàng)文章,轉(zhuǎn)載請注明出處 http://zhangdaiping.iteye.com
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
