架構設計:前后端分離之Web前端架構設計


  在前面的文章里我談到了前后端分離的一些看法,這個看法是從宏觀的角度來思考的,沒有具體的落地實現,今天我將延續上篇文章的主題,從純前端的架構設計角度談談前后端分離的一種具體實現方案,該方案和我原來設想有了很大的變化,但是核心思想沒變,就是控制層是屬於Web前端的。

  在以前文章里我說道前后端分離的核心在於把mvc的控制層歸為前端的一部分,原方案的構想在實際的生產開發里很難做到,我覺得核心還是控制層和視圖層的技術異構性,這樣后果使得系統改造牽涉面太大,導致在項目團隊里,溝通、協調以及管理成本相對較高,隨着前端技術的發展,前端開發的工程量是越來越大,難度也是越來越高,因此前端工程的項目化,工程化和獨立性越來越被人重視了,所以出現了大量的javascript MVC的富應用。如果javascript也能做到MVC模式,那么前端框架就可以拋棄異構語言的控制層,做到真正的獨立。

  要把傳統的MVC的C層從前端剝離掉,我們首先要理解下MVC的C層即控制層到底做了什么樣的事情,控制層的作用是模型層和視圖層溝通的紐帶,模型層進一步具體點就是數據層,視圖層具體點就是數據展示給用戶的方式,下面我們看看java的Web應用里,控制層和視圖層是如何耦合的呢?做過java的web開發的人第一個反應就是頁面里回嵌入大量java代碼或者使用jsp的標簽或者使用velocity,freemark這樣的模板語言,這些東西大家很自然的把它們歸為服務端的東西,但是它們卻出現在了視圖層,所以視圖層和控制層沒法解耦,其實除了這個還有一個大家很熟悉但又很少把它歸為是視圖層和控制層的耦合因素,這個因素就是頁面的跳轉,用ajax的角度描述這個因素就是頁面的同步提交,這兩個因素也就是構成了控制層的核心應用(是應用數據和頁面展示的橋梁)。

  要將前端獨立起來,控制層歸為前端是不可改變的定律,如果服務端的人太傲慢無禮,不肯放掉控制層,那么前端就必須自己來做控制層,那么前端做控制層的難點就是解決前端技術如何做到解決服務端數據展示和有時無法避免的同步提交問題,解決服務端數據展示問題就是要在javascript語言里找到替換java代碼、jsp標簽以及velcity這樣的模板語言的技術,很幸運在javascript的確擁有這樣的技術,這就是微軟公司貢獻的jQuery的模板語言jquery-tmpl,它的訪問地址是:

  https://github.com/BorisMoore/jquery-tmpl

  百度搜索的地址:

 

  http://www.baidu.com/s?wd=jquery%20tmpl&rsv_spt=1&issp=1&rsv_bp=0&ie=utf-8&tn=baiduhome_pg&rsv_sug3=8&rsv_sug4=1397&rsv_sug1=8&oq=jquery%20tm&rsv_sug2=0&f=3&rsp=0&inputT=13948

  有了javascript的模板技術,我們就可以不用在頁面再寫入服務端的任何東西,這樣就達到異構語言的控制層和前端的分離,從而摒棄服務端的控制層。而模板語言需要的數據就可以通過ajax請求發送到頁面,ajax接收到數據后傳輸到javascript的模板語言里最終就可以達到服務端數據在頁面上的展示,使用這種方式展示數據好處不僅僅局限於控制層和視圖層的解耦,同時還會提升頁面的響應效率,因為通過這種方式,數據和服務端的交換不再需要視圖展示要素即服務端直接發送個頁面,或者是頁面的片段,然后操作dom使得這些視圖性的東西展示到頁面上的行為,而現在服務端只需要傳輸需要傳輸的數據就行,這樣一個http請求的數據傳輸量會大大減少,減少http請求的數據大小是提升網站加載效率的重要指標之一,同時如果傳輸只需要最必要的數據,那么服務端和前端的交互就可以做到統一的報文格式,使用統一的報文規范,這樣會對項目管理,系統運維和維護帶來質的飛越。

  讓控制層徹底歸為web前端的第二步就是要讓web應用的同步提交操作徹底死翹翹,而傳統的同步提交只要承擔整個web應用的入口的功能即可。談到這里我想如果對web前端開發有過經驗的人看到上面這句話就很容易聯想到現在很火的單頁面開發,沒錯我的確在講單頁面開發,其實javascript MVC的最高境界就是單頁面模式。

  雖然時下的web應用是ajax的天下,但是如果我們想徹底的拋棄同步提交請求的想法真的應用到實踐中,開發人員會發現它常常會變成一個吃力不討好的事情,為什么說它是一件吃力不討好的事情,我想主要體現在兩個方面:

  第一方面:ajax請求往往是作為純數據的傳輸,那么頁面效果的顯示就需要開發人員自己操作DOM,使用各種javascript開發技巧,這就大大增加頁面開發難度和復雜度,對於一個要投入市場的web應用,其成本和風險是可想而知的。

  另一方面:同步提交頁面會讓用戶享受一種很頂級的用戶體驗,這就是瀏覽器的前進和后退體驗,如果讓ajax做前進和后退,特別是用戶和網站交互量很大的網站,這個操作可能會成為一件不可能完成的任務。

  這里我首先講如何解決前進和后退的問題,在瀏覽器的請求url地址有一個很重要的特性就是hash屬性,例如我們寫頁面時候常常會寫到這樣的語句:

1
< a  href=”#” onclick=”ftn()” id=”btn”>btn</ a >

 

  當用戶點擊這個鏈接時候,會促發click事件,可能很多人沒有留心到此時網頁請求的url后面會添加一個#號,例如:www.cnblogs.com/#,如果我們把這個鏈接改下,如下:

1
< a  href=”#sharpxiajun” onclick=”ftn()” id=”btn”>btn</ a >

 

  再點擊這個鏈接,我們會發現鏈接變成了www.cnblogs.com/#sharpxiajun,前面的#sharpxiajun就是url的hash,url的hash是不會發送給服務端的,不過在瀏覽器里有專門的事件可以監聽到它,這個事件就是hashchange事件,它是一個window的事件,瀏覽器的前進與后退支持url的hash改變,同時window可以監聽到該事件,因此我們可以通過改變url的hash再加上ajax請求就可以模擬頁面的同步提交了,同時該請求是可以使用瀏覽器的前進和后退操作。

  使用url的hash屬性模擬同步的url,那么我們就可以將頁面的url改成一個帶hash的url地址,例如傳統網站的注冊頁面地址應該是:www.cnblogs.com/register.html,現在可以改為www.cnblogs.com/#!/register,如果注冊頁面的上游頁面是www.cnblogs.com/,那么我們在注冊頁面點擊回退按鈕時候頁面就會跳轉到www.cnblogs.com/

  如果我們web前端擁有的以上我所講述的技術,那么一個web應用的控制層可以完全平移到了web前端,而web前端可以做到真正的項目獨立,到時web前端只要和服務端建立合適的報文規范,使用時下流行的json數據格式,就可以完成Web應用的開發,這樣的web應用就做到前后端的真正分離。

  使用我講到的技術開發網站,瀏覽器的通信都將是ajax,這個ajax按應用場景可以分為兩種類型:一種類型是模擬同步提交的ajax,這個請求時獲取視圖,也就是頁面,這個功能可以當做一個路由功能,這是控制層控制視圖層的操作,另一個ajax就是獲取數據,ajax獲取到數據后,通過javascript模板技術進行轉化,最后控制層將轉化的數據和視圖層結合到一起,最終將完整的頁面呈現給網站的用戶。

  Javascript做控制層其實是通過url的hash完成的,核心是使用window的hashchange事件,這里就有一個web前端開發最頭疼的問題,是不是所有瀏覽器都支持hashchange事件了?答案是:新瀏覽器都支持,最可惡的ie,在8以上包括8都支持,那么我們想讓所有瀏覽器都可以使用hashchange怎么辦來了?jquery有個插件可以讓低版本的瀏覽器支持hashchange事件,有興趣的人可以百度一下,不過如果是在移動設備上開發web應用時完全不用擔心兼容問題。

  前面我用到一個帶hash的url:www.cnblogs.com/#!/register,#!/xxx是我推薦給大伙的書寫形式,理由是:我們做一個網站都需要給搜索引擎示好,但是搜索引擎的網絡爬蟲都是抓取靜態頁面,對於ajax請求的靜態頁面往往無能為力,因此我們要讓搜索引擎的網絡爬蟲能找到我們的頁面所以在#后面加上!/,很多高級的搜索引擎會抓取到我們網頁上的內容,這里主要是指google,百度的是不是有類似的能力,俺就不清楚,這個就得問問度娘了。

  我之前在我的博客里給大伙分享了我自己寫的一個javascript框架,當時我使用一個文件,一個庫來完成我的框架,這樣的框架其實只能算是把一個Web開發里能通用的東西做了一個抽取和匯總,換種說法就是以前的框架是一個工具類大集合,但是到了我今天講的web前端的javascript框架,這樣的工具類是不能滿足我們的需求,原因是控制層被移到了web前端,這樣web應用的數據模型及模型層和控制層對視圖層的路由功能同時也遷移到了web前端,那么某一個頁面對應的數據模型以及對應的視圖頁面,我們應該讓它和別的數據模型和對應頁面有一個明顯的界線,具體實現里就是一個視圖及一個頁面對應的javascript代碼應該要模塊化,所以我們最好一個頁面對應一個javascript文件,這樣我們就要對javascript代碼進行模塊化管理,要引入requieJS或者國產的seajs工具,具體的使用有興趣的童鞋可以百度或者google一下。

  如果我們不會用requieJS和seajs怎么辦了?大型網站的javascript代碼和css代碼在生產上都會盡量的合並成少量的文件,因此我這里建議大家要用面向對象的方式組織自己的javascript代碼,這里我推薦一個借鑒與jQuery架構類似的javascript框架模板:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
function ($,params){
     function  MyObj = {
         return  this ._init.apply( this ,arguments);
}
myObj.fn = myobj.prototype;
myObj.fn =  function (){
     return  {
         _init: function (){ // 初始化方法
             this .setting = arguments;
return  this ;
},
_bindEvt: function (){ // 事件綁定
代碼…
     return  this ;
},
_pageLoad: function (){
_bindEvt();
     代碼…
     return  this ;
}
}
};
// 給類添加屬性或方法,相當於靜態變量
myObj.extend =  function (obj){
     var  extended = obj. extended;
     for  ( var  in  obj){
         myObj.fn[i] = obj[i];
}
if  (extended) extend(myObj);
};
myObj.load =  function (param){
     return  new  myObj(params)._pageLoad();
}
return  myObj;
})(jQuery,params,undefined)

 

  該框架的load方法相當於java的main函數,這里我們使用javascript對象的技術構建對象,那么該對象對外就很容易擴展,每個原型prototype方法都會返回this指針這樣就可以達到jQuery里方法連綴的寫法。

  其實這樣的結構最后也能應用到requieJS和seajs里面,這樣寫的javascript代碼的結構性和層次性更好,擴展性更強。

  好了文章寫完了,本篇文章一氣呵成,難免有遺漏錯誤地方,到時還請認真的童鞋及時指出。

 

 
 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM