這篇文章主要介紹了JavaScript的Backbone.js框架入門學(xué)習(xí)指引, 其中特別講到了Backbone中的關(guān)鍵部分Router路由器,需要的朋友可以參考下
1.簡(jiǎn)介
最近在做一個(gè)大型網(wǎng)上銀行項(xiàng)目前端的優(yōu)化,需要使用一個(gè)胖客戶端的優(yōu)化,大概思路就是前端通過(guò)Ajax 請(qǐng)求去后端獲取數(shù)據(jù),以Jason的格式返回,然后顯示在頁(yè)面上。由于這個(gè)系統(tǒng)非常龐大,胖客戶端方案難免需要在客戶端寫(xiě)大量的JS代碼。我想對(duì)于任何團(tuán)隊(duì)來(lái)說(shuō),大量的,非結(jié)構(gòu)化的代碼維護(hù)起來(lái)都非常的不方便。所以BackBone進(jìn)入了我的視線。
它提供了一種途徑可以讓你結(jié)構(gòu)化你的JS代碼,讓你以面向?qū)ο蟮姆绞絹?lái)組織你的前端JS代碼。這就好比我們?cè)谇岸藨?yīng)用Domain Driven Design. 我們可以把一個(gè)非常大的項(xiàng)目按模塊切分。 每個(gè)模塊里面又可以按照BackBone的要求切分成View, Model, Router。
通過(guò)backbone,你可以把你的數(shù)據(jù)當(dāng)作Models,通過(guò)Models你可以創(chuàng)建數(shù)據(jù),進(jìn)行數(shù)據(jù)驗(yàn)證,銷毀或者保存到服務(wù)器上。當(dāng)界面上的操作引起model中屬性的變化時(shí),model會(huì)觸發(fā)change的事件;那些用來(lái)顯示model狀態(tài)的views會(huì)接受到model觸發(fā)change的消息,進(jìn)而發(fā)出對(duì)應(yīng)的響應(yīng),并且重新渲染新的數(shù)據(jù)到界面。在一個(gè)完整的backbone應(yīng)用中,你不需要寫(xiě)那些膠水代碼來(lái)從DOM中通過(guò)特殊的id來(lái)獲取節(jié)點(diǎn),或者手工的更新HTML頁(yè)面,因?yàn)樵趍odel發(fā)生變化時(shí),views會(huì)很簡(jiǎn)單的進(jìn)行自我更新。
2.特點(diǎn)
Backbone是一個(gè)輕量級(jí)的前端框架,用于結(jié)構(gòu)化管理頁(yè)面中的大量JS,建立與服務(wù)器、視圖間的無(wú)縫連接,為構(gòu)建復(fù)雜的應(yīng)用提供基礎(chǔ)框架。
下面我先簡(jiǎn)單地闡述下Backbone的主要特點(diǎn)及特性:
2.1 輕量級(jí)
Backbone的源碼只有1000行左右(去注釋和空行后),文件大小只有16KB,加上依賴庫(kù)Underscore,也僅有29KB。
你只需要花一點(diǎn)時(shí)間,就能輕松了解Backbone內(nèi)部實(shí)現(xiàn);或編寫(xiě)少量代碼,來(lái)重載Backbone的部分機(jī)制;如果你想在Backbone的基礎(chǔ)上做二次開(kāi)發(fā),也并不是一件復(fù)雜的事情。
2.2 結(jié)構(gòu)化
Backbone可以輕松將頁(yè)面中的數(shù)據(jù)、邏輯、視圖解耦,依照Backbone進(jìn)行代碼結(jié)構(gòu)組織,你可以將項(xiàng)目中的數(shù)據(jù)交互、業(yè)務(wù)邏輯、用戶界面等工作,分配給多個(gè)同事同時(shí)開(kāi)發(fā),并能有序地組織到一起。同時(shí),這對(duì)于大型和復(fù)雜項(xiàng)目的維護(hù)開(kāi)發(fā)非常有幫助。
2.3 繼承機(jī)制
在Backbone中,模塊是可以被繼承的,你可以通過(guò)面向?qū)ο蟮姆绞綄?yīng)用中的數(shù)據(jù)模型、集合、視圖有序地組織,讓整個(gè)架構(gòu)更加清晰;也可以方便地重載和擴(kuò)展自定義方法。
2.4 建立與服務(wù)器的無(wú)縫連接
在Backbone中內(nèi)置了一套與服務(wù)器數(shù)據(jù)的交互規(guī)則(如果你了解REST架構(gòu),就能夠輕松地理解它們),而數(shù)據(jù)的同步工作會(huì)在Model中自動(dòng)進(jìn)行,前端開(kāi)發(fā)人員只需對(duì)客戶端數(shù)據(jù)的進(jìn)行操作,Backbone會(huì)自動(dòng)將操作的數(shù)據(jù)同步到服務(wù)器。
這是件非常有趣的事情,因?yàn)榉?wù)器數(shù)據(jù)接口對(duì)前端開(kāi)發(fā)者來(lái)說(shuō)是透明的,他們不需要再關(guān)心如何和服務(wù)器交互。
然而服務(wù)器提供的數(shù)據(jù)接口也需要兼容Backbone的規(guī)則,對(duì)于一個(gè)新的項(xiàng)目來(lái)說(shuō),我們可以嘗試使用這套規(guī)則來(lái)構(gòu)建接口。但如果你的項(xiàng)目中已經(jīng)有一套穩(wěn)定的接口,你可能會(huì)擔(dān)心接口改造的風(fēng)險(xiǎn)。
沒(méi)關(guān)系,我們可以通過(guò)重載Backbone.sync方法來(lái)適配現(xiàn)有的數(shù)據(jù)接口,針對(duì)不同的客戶端環(huán)境,我們還可以實(shí)現(xiàn)不同的數(shù)據(jù)交互方式。例如:用戶通過(guò)PC瀏覽器使用服務(wù)時(shí),數(shù)據(jù)會(huì)實(shí)時(shí)同步到服務(wù)器;而用戶通過(guò)移動(dòng)終端使用服務(wù)時(shí),考慮到網(wǎng)絡(luò)環(huán)境問(wèn)題,我們可以先將數(shù)據(jù)同步到本地?cái)?shù)據(jù)庫(kù),在合適的時(shí)候再同步到服務(wù)器。而這些只需要你重載一個(gè)方法就可以實(shí)現(xiàn)。
2.5 界面事件管理
在MVC中,我們希望能將界面展現(xiàn)和業(yè)務(wù)邏輯完全分離,但對(duì)于用戶產(chǎn)生的交互事件(如單擊事件),我們卻常常通過(guò)類似jQuery中的bind方法進(jìn)行獲取和綁定。
Backbone中的視圖幫助我們將用戶事件和執(zhí)行方法有序的組織起來(lái),這只需要我們聲明一個(gè)簡(jiǎn)單的表達(dá)式,例如:
events: {
// 單擊id為”save”的元素時(shí),執(zhí)行視圖的add方法
'click #save': 'add',
'mousedown .button': 'show',
'mouseover .button': 'hide'
}
在表達(dá)式中,事件名稱可以是任意的DOM事件(如click、mouseover、keypress等),元素可以是jQuery支持的任意選擇器(如標(biāo)簽選擇器、id選擇器、class選擇器等)。
視圖會(huì)自動(dòng)將表達(dá)式中的事件綁定到選擇器元素,當(dāng)元素的事件被觸發(fā)后,視圖會(huì)自動(dòng)調(diào)用表達(dá)式中綁定的方法。
2.6 輕量級(jí)模板解析
模板解析是Underscore中提供的一個(gè)方法。為什么我要在介紹Backbone特性時(shí)引入U(xiǎn)nderscore中的方法?因?yàn)樵摲椒軒椭覀兏玫胤蛛x視圖結(jié)構(gòu)和邏輯,且Underscore是Backbone必須依賴的庫(kù)。
模板解析方法能允許我們?cè)贖TML結(jié)構(gòu)中混合嵌入JS代碼,就像在JSP頁(yè)面中嵌入Java代碼一樣:
<ul>
<% for(var i = 0; i < len; i++) { %>
<li><%=data[i].title%></li>
<% } %>
</li>
通過(guò)模板解析,我們不需要在動(dòng)態(tài)生成HTML結(jié)構(gòu)時(shí)拼接字符串,更重要的是,我們可以將視圖中的HTML結(jié)構(gòu)獨(dú)立管理(例如:不同的狀態(tài)可能會(huì)顯示不同的HTML結(jié)構(gòu),我們可以定義多個(gè)單獨(dú)的模板文件,按需加載和渲染即可)。
2.7 自定義事件管理
在Backbone中,你可以使用on或off方法綁定和移除自定義事件。在任何地方,你都可以使用trigger方法觸發(fā)這些綁定的事件,所有綁定過(guò)該事件的方法都會(huì)被執(zhí)行,如:
var model = new Backbone.Model();
// 在model對(duì)象中向自定義事件custom綁定兩個(gè)函數(shù)
model.on('custom', function(p1, p2) {
// todo
});
model.on('custom', function(p1, p2) {
// todo
});
// 觸發(fā)custom事件,將調(diào)用上面綁定的兩個(gè)函數(shù)
model.trigger('custom', 'value1', 'value2');
// 移除custom事件中綁定的所有方法
model.off('custom');
// 觸發(fā)custom事件,但不會(huì)執(zhí)行任何函數(shù),已經(jīng)事件中的函數(shù)已經(jīng)在上一步被移除
model.trigger('custom');
如果你熟悉jQuery,你會(huì)發(fā)現(xiàn)它們與jQuery中的bind、unbind和trigger方法非常類似。
另外,Backbone支持一個(gè)特殊事件”all”,當(dāng)在一個(gè)對(duì)象中綁定了名為”all”的事件后,該對(duì)象在觸發(fā)任何事件時(shí),都會(huì)同時(shí)觸發(fā)”all”事件中綁定的方法。有時(shí)這種方法會(huì)非常有用,例如我們可以通過(guò)”all”事件監(jiān)聽(tīng)對(duì)象狀態(tài)的變化。
3.路由器
在單頁(yè)應(yīng)用中,我們通過(guò)JavaScript來(lái)控制界面的切換和展現(xiàn),并通過(guò)AJAX從服務(wù)器獲取數(shù)據(jù)。
可能產(chǎn)生的問(wèn)題是,當(dāng)用戶希望返回到上一步操作時(shí),他可能會(huì)習(xí)慣性地使用瀏覽器“返回”和“前進(jìn)”按鈕,而結(jié)果卻是整個(gè)頁(yè)面都被切換了,因?yàn)橛脩舨⒉恢浪幱谕粋€(gè)頁(yè)面中。
對(duì)于這個(gè)問(wèn)題,我們常常通過(guò)Hash(錨點(diǎn))的方式來(lái)記錄用戶的當(dāng)前位置,并通過(guò)onhashchange事件來(lái)監(jiān)聽(tīng)用戶的“前進(jìn)”和“返回”動(dòng)作,但我們發(fā)現(xiàn)一些低版本的瀏覽器(例如IE6)并不支持onhashchange事件。
Backbone提供了路由控制功能,通過(guò)Backbone提供的路由器,我們能通過(guò)一個(gè)簡(jiǎn)單的表達(dá)式將路由地址和事件函數(shù)綁定在一起,例如:
var CustomRouter = Backbone.Router.extend({
routes : {
'' : 'index', // 當(dāng)URL Hash在根目錄時(shí)執(zhí)行index方法:url#
'list' : 'getList', // 當(dāng)URL Hash在list節(jié)點(diǎn)時(shí)執(zhí)行g(shù)etList方法:url#list
'detail/:id' : 'query', // 當(dāng)URL Hash在detail節(jié)點(diǎn)時(shí)執(zhí)行query方法,并將detail后的數(shù)據(jù)作為參數(shù)傳遞給query方法:url#list/1001
'*error' : 'showError' // 當(dāng)URL Hash不匹配以上規(guī)則時(shí), 執(zhí)行error方法
},
index : function() {
alert('index');
},
getList : function() {
alert('getList');
},
query : function(id) {
alert('query id: ' + id);
},
showError : function(error) {
alert('error hash: ' + error);
},
});
var custom = new CustomRouter();
Backbone.history.start();
請(qǐng)嘗試將這段代碼復(fù)制到你的頁(yè)面中,并依次訪問(wèn)以下地址(其中URL表示你的頁(yè)面地址):
URL
URL#list
URL#detail/1001
URL#hash1
URL#hash2
請(qǐng)?jiān)僭囍褂脼g覽器的“返回”和“前進(jìn)”按鈕來(lái)回切換剛剛輸入的地址。
你可以看到,當(dāng)URL Hash發(fā)生變化時(shí),會(huì)執(zhí)行所綁定的方法,當(dāng)遇到?jīng)]有定義的Hash時(shí),都會(huì)執(zhí)行showError方法,并將未定義的Hash傳遞給該方法。
Backbone默認(rèn)會(huì)通過(guò)Hash的方式來(lái)記錄地址的變化,對(duì)于不支持onhashchange的低版本瀏覽器,會(huì)通過(guò)setInterval心跳監(jiān)聽(tīng)Hash的變化,因此你不必?fù)?dān)心瀏覽器的兼容性問(wèn)題。
對(duì)于支持HTML5 pushState特性的瀏覽器,Backbone還允許你通過(guò)pushState來(lái)創(chuàng)建個(gè)性化的URL,但是這需要你的Web服務(wù)器做一些適配。
3. Backbone的適用性
Backbone并不像jQuery那樣具有非常強(qiáng)的適用性,如果你正準(zhǔn)備構(gòu)建一個(gè)大型或復(fù)雜的單頁(yè)Web應(yīng)用,那么Backbone再適合不過(guò)。
如果想將Backbone應(yīng)用到你的網(wǎng)站頁(yè)面中,且頁(yè)面中并沒(méi)有復(fù)雜的邏輯和結(jié)構(gòu),那么這只會(huì)讓你的頁(yè)面更加繁瑣和難以維護(hù)。
如果你的項(xiàng)目并不復(fù)雜,但你卻深深喜歡它的某個(gè)特性(可能是數(shù)據(jù)模型、視圖管理或路由器),那么你可以將這部分源碼從Backbone中抽取出來(lái),因?yàn)樵贐ackbone中,各模塊間的依賴并不是很強(qiáng),你能輕易的獲取并使用其中的某一個(gè)模塊。
4. 依賴庫(kù)
你不能獨(dú)立使用Backbone,因?yàn)樗幕A(chǔ)函數(shù)、DOM操作、AJAX都依賴于第三方庫(kù)。
4.1 Underscore
(必選)
Underscore是一個(gè)用于提高開(kāi)發(fā)效率的基礎(chǔ)函數(shù)庫(kù),它封裝了對(duì)集合、數(shù)組、對(duì)象、函數(shù)的常用操作,就像jQuery封裝DOM對(duì)象一樣,你能通過(guò)Underscore輕易地訪問(wèn)和操作JavaScript內(nèi)部對(duì)象。
Underscore還提供了一些非常實(shí)用的函數(shù)方法,如:函數(shù)節(jié)流、模板解析等。
關(guān)于Underscore中一些主要的方法,我會(huì)在下一章詳細(xì)介紹,但在此之前你必須了解:Underscore是Backbone必須依賴的庫(kù),因?yàn)樵贐ackbone中許多實(shí)現(xiàn)都是基于Underscore。
4.2 jQuery和Zepto
(可選)
相信你對(duì)jQuery一定不會(huì)陌生,它是一個(gè)跨瀏覽器的DOM和AJAX框架。
而對(duì)于Zepto你可以理解為“移動(dòng)版的jQuery”,因?yàn)樗?、更快、更適合在移動(dòng)終端設(shè)備的瀏覽器上運(yùn)行,它與jQuery語(yǔ)法相同,因此你能像使用jQuery那樣使用它。
Zepto目前僅支持Webkit內(nèi)核的瀏覽器,因此它能兼容iOS、Adnroid、塞班、黑莓和Meego等大部分移動(dòng)系統(tǒng),而對(duì)于Windows Phone或Firefox OS,它暫時(shí)還不支持。
因?yàn)閖Query和Zepto語(yǔ)法相同,因此對(duì)于Backbone來(lái)說(shuō),你無(wú)論是使用jQuery還是Zepto,都沒(méi)有問(wèn)題(當(dāng)然,你不可能兩個(gè)同時(shí)都用到)。
在Backbone中,DOM選擇器、DOM事件和AJAX,都使用了jQuery的方法。這里之所以所它們是可選的,是假設(shè)你沒(méi)有用到Backbone中的視圖和AJAX數(shù)據(jù)同步功能,那么就不需要導(dǎo)入它們。
如果你不想使用jQuery或Zepto,而是使用其它的、或自定義庫(kù),只要你的庫(kù)中實(shí)現(xiàn)了與jQuery語(yǔ)法相同的DOM選擇器、事件管理和AJAX方法,那么就不會(huì)任何問(wèn)題。
Backbone允許你通過(guò)setDomLibrary方法動(dòng)態(tài)配置需要使用的第三方庫(kù),這種情況常常用于:
你的自定義庫(kù)雖然包含了和jQuery相同語(yǔ)法的方法,但全局變量并不是$,而且你想保持現(xiàn)有的命名。這時(shí)你可以通過(guò)setDomLibrary方法將其設(shè)置為Backbone內(nèi)部引用的對(duì)象。
你希望通過(guò)檢查用戶的環(huán)境,來(lái)決定更適合使用哪一個(gè)庫(kù)。例如:如果用戶使用PC瀏覽器訪問(wèn),則載入jQuery,如果用戶通過(guò)移動(dòng)終端訪問(wèn),則載入Zepto。
2025國(guó)考·省考課程試聽(tīng)報(bào)名