更新時(shí)間:2017-06-21 來源:黑馬程序員web前端開發(fā)培訓(xùn)學(xué)院 瀏覽量:
作為剛接觸前端的不久的童鞋,大家都會(huì)興奮于CSS和JS所帶來漂亮界面,然而,前端工程師除了UI重構(gòu)外,還有非常重要的職責(zé)在正確的區(qū)域渲染出服務(wù)端的數(shù)據(jù)。畢竟,我們要構(gòu)建一個(gè)大的web應(yīng)用,必然不是普普通通的靜態(tài)頁面構(gòu)成。
下文將羅列將來前端工程師應(yīng)該必備的同后端打交道的常用技能。
服務(wù)端渲染:
談起服務(wù)端渲染,對于動(dòng)態(tài)服務(wù)而言,這個(gè)世界上跑的大多數(shù)頁面都經(jīng)歷過服務(wù)端的數(shù)據(jù)渲染,接口->前端賦值->模版渲染 。這一切都在服務(wù)器完成,我們查看源碼時(shí)候,可以看到完整的html代碼,包括每個(gè)數(shù)據(jù)值。
常用的php模版有,Smarty,Blade,Mustache,如果你們團(tuán)隊(duì)使用Smarty,我們可以看到一些view的文件里會(huì)前套Smarty的模版語言;
1 | < font style = "color:rgb(51, 51, 51)" >< div > {foreach $list as $item} < h3 >{$item['name']}</ h3 > < p >{$item['desc']}</ p > {/foreach} </ div ></ font > |
如果Node,js作為服務(wù)端的話,這個(gè)時(shí)候我們可以使用前端模版渲染的模塊,比如ejs,doT,jade等等。
注意不同的模版可能存在不同模版語法,需要自己學(xué)習(xí)使用.
AJAX:
當(dāng)然服務(wù)端渲染隨著單頁應(yīng)用以及Restful接口的興起,Ajax逐漸成為目前前后端交流最為頻繁的方式。Ajax實(shí)際核心是,我們通過對該對象的操作來進(jìn)行異步的數(shù)據(jù)請求。
1 | < font style = "color:rgb(51, 51, 51)" >// 一般流程[/color][/p] varoReq = new(); oReq.addEventListener( "load", function(res){ // your code to do something}); oReq.open( "GET", "http://www.example.org/example.txt"); oReq.send();</ font > |
實(shí)際上我們接觸到最多jQuey就有很好的封裝,比如$.ajax,$.post等,如果用Angular的話我們可以用$http服務(wù),除了這些之外,我們可以使用第三方的Ajax庫qwest等。
如果使用Ajax的話,我們不得不面臨一些問題,由于同源限制的問題,我們不得不去克服這個(gè)問題,這個(gè)時(shí)候我們可以要求服務(wù)端,設(shè)置header頭,header('Access-Control-Allow-Origin: *');或者叫設(shè)置nginx配置.
1 | < font style = "color:rgb(51, 51, 51)" >< font style = "color:rgb(51, 51, 51)" >add_header 'Access-Control-Allow-Origin''http://yourweb.com'; add_header 'Access-Control-Allow-Credentials''true'; add_header 'Access-Control-Allow-Methods''GET';</ font ></ font > |
當(dāng)然這不是最好的做法,實(shí)際現(xiàn)在我們也可以這么做:
ajax -> 代理 -> API
我們可以用php的curl或者通過服務(wù)器的配置來實(shí)現(xiàn)反向代理。從而達(dá)到同源的效果。
前端工程師一定要要求每次請求的數(shù)據(jù)接口一嚴(yán)格遵循基礎(chǔ)的數(shù)據(jù)結(jié)構(gòu)要求,盡管js是弱變量類型語言,但是我們還是應(yīng)該嚴(yán)格要求,是數(shù)組,就不應(yīng)該是對象,是數(shù)字就不應(yīng)該是字符串,這樣做有利于降低隱藏bug并且提升前后端工作效率。
JSONP:
JSONP算作JSON的一種"使用模式",可用于解決主流瀏覽器的跨域數(shù)據(jù)訪問的問題。由于CORS的支持,我們可以簡單的將數(shù)據(jù)封裝成一個(gè)js腳本請求,當(dāng)然我們在jquery中會(huì)用到。
1 | < font style = "color:rgb(51, 51, 51)" >< font style = "color:rgb(51, 51, 51)" >functionlogResults(json){ console.log(json); } $.ajax({ url: "https://yourapi.com/api", dataType:"jsonp", jsonpCallback: "logResults"}); Comet</ font ></ font > |
Comet:
聊Comet我們還得說下短輪詢,由于某些特定的業(yè)務(wù)需求,比如通知,我們需要有及時(shí)的數(shù)據(jù)更新,我們能夠想到的就是使用setInterval每隔一定時(shí)間比如10s去獲取一次請求,從而做到一些通知更新,但是這并不一種高效的做法,這會(huì)增加服務(wù)器的請求數(shù)量。這個(gè)時(shí)候有了另外一種概念,“反向Ajax”,由服務(wù)器進(jìn)行數(shù)據(jù)推送, Comet能夠讓信息近乎實(shí)時(shí)的被推送到頁面上,非常適合要求實(shí)時(shí)性的獲取的數(shù)據(jù)的頁面。
如圖所示,就是一個(gè)簡單的Comet模型,就是數(shù)據(jù)請求后掛起,直到有數(shù)據(jù)響應(yīng)推送到客戶端,這個(gè)時(shí)候客戶端再發(fā)起一個(gè)新的連接。
這樣相對來說可以減少一定數(shù)量的請求,以及數(shù)據(jù)的及時(shí)響應(yīng),從而一定意義的實(shí)現(xiàn)所謂推送。
一個(gè)簡單的PHP Demo代碼,就是我們需要這端代碼一直運(yùn)行著...
while( true) { set_time_limit( 0); echo 'data'; flush(); b_flush(); sleep( 3); }
JavaScript:
1 | <font style= "color:rgb(51, 51, 51)" >[mw_shl_code=html, true ]functioncreateStreamingClient(url,progress,finished){ varxhr= new (),received= 0; xhr.open( "get" ,url, true ); xhr.onreadystatechange= function (){ varresult; if (xhr.readyState== 3){ result=xhr.responseText.substring(received); received+=result.length; progress(result); }elseif(xhr.readyState== 4){ finished(xhr.responseText); } }; xhr.send( null ); returnxhr; } // var client = createStreamingClient(url,fuc1,func2)</font> |
SSE Server-Sent Events:
SSE是圍繞只讀Comet交互推出的API或者模式。SSE API用于創(chuàng)建到服務(wù)器的單向連接,服務(wù)器通過這個(gè)連接可以發(fā)送任意數(shù)量的數(shù)據(jù)。服務(wù)器響應(yīng)的MIME類型必須是text/event-stream,而且是瀏覽器中的Java API能解析的格式輸出。
現(xiàn)對于Comet,我們可以看出我們只進(jìn)行了一次連接,然后服務(wù)端會(huì)去控制數(shù)據(jù)的響應(yīng),從而發(fā)送給客戶端。這樣相對來說,但是如同定義的描述,這種只適合只讀數(shù)據(jù)的情形。比如一些通知和狀態(tài)碼這樣的。SEE的使用非常簡單,只需要掌握這幾個(gè)api就行:
1 2 3 4 | <font style= "color:rgb(51, 51, 51)" >vares = newEventSource( 'http://your.api.com' [/color][/p] functionlistener(event){ console.log(event.data); } // 創(chuàng)建一個(gè)SSE連接 es.addEventListener( "open" , listener); // 響應(yīng)獲取消息的事件 es.addEventListener( "message" , listener); // 發(fā)生錯(cuò)誤 es.addEventListener( "error" , listener);</font> |
注意:如果在回話過程中遇見錯(cuò)誤后,默認(rèn)程序會(huì)重新發(fā)起一次新的連接,從而防止掛掉就不再響應(yīng)了
服務(wù)端(node,php)的代碼,可以參考:https://github.com/Yaffle/EventSource
Web Sockets:
HTML5 WebSocket 設(shè)計(jì)出來的目的就是要取代輪詢和 Comet 技術(shù),使客戶端瀏覽器具備像 C/S 架構(gòu)下桌面系統(tǒng)的實(shí)時(shí)通訊能力。 瀏覽器通過 Java 向服務(wù)器發(fā)出建立 WebSocket 連接的請求,連接建立以后,客戶端和服務(wù)器端就可以通過 TCP 連接直接交換數(shù)據(jù)。也就是我們可以使用web技術(shù)構(gòu)建實(shí)時(shí)性的程序比如聊天游戲等應(yīng)用。
其實(shí)Web Sockets 的API很少,就下面這些:
1 2 3 4 5 6 | <font style= "color:rgb(51, 51, 51)" > websocket = newWebSocket( "ws://your.socket.com:9001" ); // 大開[/color][/p] websocket.onopen = function (evt){ /* do stuff */ }; //on open event // 當(dāng)web socket關(guān)閉 websocket.onclose = function (evt){ /* do stuff */ }; // 進(jìn)行通信時(shí) websocket.onmessage = function (evt){ /* do stuff */ }; // 發(fā)生錯(cuò)誤時(shí) websocket. = function (evt){ /* do stuff */ }; // 向服務(wù)器發(fā)發(fā)送消息 websocket.send(message); //send method websocket.close(); //close method</font> |
對于服務(wù)端的話,PHP支持了很多socket 相關(guān)api,但是我們可以使用更加成熟的框架(實(shí)用)比如phpsocket.io,Ratchet.當(dāng)然node.js寫 socket也非常得心應(yīng)手,node.js對高并發(fā)支持相對較好,可以使用http://socket.io/。
服務(wù)端大概會(huì)做下面的事情: + 創(chuàng)建一個(gè)socket + 綁定地址和端口 + 監(jiān)聽進(jìn)入的連接 + 接收新的連接 + web socket 握手 + 解碼數(shù)據(jù)
小結(jié):
說了那么多簡單總結(jié)下,大家想明白幾點(diǎn)就行了,客戶端與服務(wù)端誰先主動(dòng),是否強(qiáng)調(diào)數(shù)據(jù)的實(shí)時(shí)性。
Web前端開發(fā)培訓(xùn)之全面的前端開發(fā)指南:HTML、CSS
2017-06-21Web前端開發(fā)培訓(xùn)之全面的前端開發(fā)指南:JavaScript
2017-06-21Web前端開發(fā)培訓(xùn)之HTML5新手入門指南
2017-06-21Web前端開發(fā)培訓(xùn)之HTML5 如何重新定義web
2017-06-21WEB前端培訓(xùn)之David Geary對HTML5 的 2D 視頻游戲詳細(xì)剖析思路一
2017-06-15WEB前端培訓(xùn)之David Geary對HTML5 的 2D 視頻游戲詳細(xì)剖析思路二
2017-06-15