很是慚愧,還記得2016年那人生中第一次面試,被問到有沒用過ajax?你怎麼解決跨域問題時,我回答沒用過。。不知道的時候,面試官那一臉茫然,對於當時覺得js只是作個輪播圖,作點小動畫的我來講,ajax、跨域什麼的就如同一道難以逾越的高牆通常。。javascript
在後來的實習中終於接觸到而且運用起了ajax,跨域也解決過,不過是後端同事解決的(如今才知道那應該就是CORS了吧),因此jsonp究竟是啥,每次搜索完看了一下就放棄了。html
本文內容淺顯,適合人羣:
1.不懂什麼是跨域
2.不想本身弄兩個不一樣域名進行跨域測試的童鞋java
個人理解是,當用戶對不一樣協議或不一樣端口或不一樣域名的資源進行訪問時,就是跨域。jquery
罪魁禍首:同源策略面試
同源定義:即同一域,即相同協議&相同端口&相同域名&相同子域名ajax
同源策略規定:XHR對象只能訪問與包含它的頁面位於同一域中的資源,有利於預防一些惡意行爲。json
解決辦法有不少,CORS、iframe、h5新特性postMessage等,而比較簡單的方法就是今天着重介紹的jsonp。後端
解決依據:儘管不能訪問非本域的動態資源,可是相似js文件、樣式、圖片等靜態資源是能夠訪問的!就是經過這個「漏洞」來解決跨域問題。用<script>標籤中的src來寫入跨域數據的url,這樣就能繞過同源策略了。。「老師,他做弊!」api
JSONP,JSON with Padding的簡寫,這個全稱對jsonp的理解仍是有必定的幫助的。填充式JSON或者說是參數式JSON。JSONP的語法和JSON很像,簡單來講就是在JSON外部用一個函數包裹着。JSONP基本語法以下:跨域
callback({ "name": "kwan" , "msg": "獲取成功" });
JSONP兩部分組成:回調函數和裏面的數據。回調函數是當響應到來時,應該在頁面中調用的函數,通常是在發送過去的請求中指定。
JSONP原理:
剛纔的解決依據可知,JSONP原理就是動態插入帶有跨域url的<script>標籤,而後調用回調函數,把咱們須要的json數據做爲參數傳入,經過一些邏輯把數據顯示在頁面上。
我想說這個JSONP我看了不少次,參考過不一樣的文章,原理都會背了,結果本身寫一個出來,傻眼。。
網上有不少文章,良心一點的會配有些代碼解釋,然而對小白來講,要本身down個WAMP什麼的服務器集成軟件或者本身搭個服務器,再弄兩個不一樣源的html才能進行模擬跨域,這真的。。。。好麻煩。。
終於,看到了一篇文章,一個經過調用api接口來模擬跨域請求數據的DEMO,實在感謝啊!這纔是我所要的好嗎!(連接在本文最後)
你再怎麼懂原理,再怎麼會JSONP基本語法,不真正執行一下你其實仍是懵逼。
固然,我認爲我仍是須要模擬不一樣源的跨域請求才對真正弄懂跨域有必定好處。
下面展現的代碼源於那篇文章,需求是輸入歌名,點擊搜索後,跨域請求API接口,返回數據後,顯示專輯名在頁面。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>JSONP</title> </head> <body> <input type="text" id="song" name=""> <input type="button" id="song_search" value="歌曲搜索" name=""> <br /> <div style="width:200px;height:230px;background:pink" id="song_list"></div> <script type="text/javascript" src="http://code.jquery.com/jquery-2.1.1.min.js"></script> <script type="text/javascript"> var searchJsonCallback=function(data){ //遍歷查詢結果 var alb_html=''; for(var i in data.list){ alb_html+='<span>專輯:</span><div style="color:black">'+data.list[0].albumname+'</div>'; } $("#song_list").html(alb_html); }; $("#song_search").on("click",function(){ var keyword=$("#song").val(); if(keyword==undefined||keyword==""){ alert("歌曲搜索不能爲空"); return false; }else{ var url = "http://cgi.music.soso.com/fcgi-bin/fcg_search_xmldata.q?source=10&w="+keyword+"&perpage=1&ie=utf-8"; // 建立script標籤,設置其屬性 var script = document.createElement('script'); script.setAttribute('src', url); // 把script標籤加入head,此時調用開始 document.getElementsByTagName('head')[0].appendChild(script); } }); </script> </body> </html>
下面是我對以上代碼的一些文字解釋:
1)點擊按鈕後動態插入跨域數據,而後因爲此接口用searchJsonCallback({})來封裝json格式數據,所以可看做是調用一個函數,同時把json數據做爲參數傳入
2)因此當動態插入script標籤後,寫好了的searchJsonCallback()函數將被調用,參數data就是json數據,而後經過遍歷渲染到DOM上,完成整個跨域獲取數據流程
總結步驟:觸發click事件-動態插入帶有API接口的script標籤-根據回調函數名調用函數-遍歷數據-渲染到頁面
注意了,千萬不要認爲用了jQuery ajax,就是經過它來實現跨域請求,其實只是由於它很好地封裝了JSONP而已
用jQuery ajax原理和上面的是同樣的,只不過咱們不須要手動的插入script標籤以及定義回調函數。jquery會自動生成一個全局函數來替換callback=?中的問號,以後獲取到數據後又會自動銷燬,實際上就是起一個臨時代理函數的做用。
因而對上面的代碼進行修改,而且把請求數據改成每次顯示5條:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>JSONP2</title> </head> <body> <input type="text" id="song" name=""> <input type="button" id="song_search" value="歌曲搜索" name=""> <br /> <div style="width:200px;height:230px;background:pink" id="song_list"></div> <script type="text/javascript" src="http://code.jquery.com/jquery-2.1.1.min.js"></script> <script type="text/javascript"> $("#song_search").on("click",function(){ var keyword=$("#song").val(); if(keyword==undefined||keyword==""){ alert("歌曲搜索不能爲空"); return false; }else{ $.ajax({ url: 'http://cgi.music.soso.com/fcgi-bin/fcg_search_xmldata.q?source=10&w='+keyword+'&perpage=5&ie=utf-8', type: 'GET', dataType: 'jsonp', jsonp:'callback', jsonpCallback: 'searchJsonCallback', success:function(data){ //遍歷查詢結果 var alb_html=''; //建立一個變量用於DOM拼接 for(var i in data.list){ alb_html+='<p style="color:black">'+data.list[i].albumname+'</p>'; console.log(data.list[i].singername); } var name_html='<span>專輯:</span>'; var sum_html=name_html+alb_html; $("#song_list").html(sum_html); } }); } }); </script> </body> </html>
關於jsonp、jsonpCallback兩個屬性,部分解釋一直沒看懂,以下:
jsonp: "callback",
//傳遞給請求處理程序或頁面的,用以得到jsonp回調函數名的參數名(通常默認爲:callback)
jsonpCallback:"handler",
//自定義的(?)jsonp回調函數名稱,默認爲jQuery自動生成的隨機函數名,也能夠寫"?",jQuery會自動爲你處理數據
直到有次看了下Network,懂了。其實就是拼接到url時想要顯示的內容。
如上面狀況,url則會變成"http://...&perpage=5&ie=utf-8&callback=searchJsonCallback&..."
因此簡單來講,
jsonp就是至關於一個名字,一個參數名
jsonpCallback就是回調函數名,用來包裹JSON數據的
而後將jsonpCallback定義的函數賦值給jsonp定義的參數上,
最後拼接在url末尾完成參數傳遞。
注意:jsonp能夠隨便寫,不寫也行,反正默認是callback
但jsonpCallback必須是對應其返回數據的函數名,此API接口返回的數據外圍用searchJsonCallback()包裹數據,所以只能是這個
(有些文章說這個也是能夠自定義的,但我測試時隨便寫就報錯了。。可能由於這個API接口固定了函數名吧)
其實上面這些例子更方便將理論用於實踐,畢竟數據等都是現成的,跨域問題也是常見的開發問題,感受就不必大費周章才能進行模擬跨域(因此我上面說本身弄服務器那種方法略麻煩)
參考資料:
上面提到的原文連接:(惋惜沒有CORS舉例)
http://www.cnblogs.com/st-les...
另外一篇幫助理解的文章:
http://blog.csdn.net/u0139455...
還有不少良心文章就不一一列舉了,此次是首次將跨域理論落實到實踐,以爲很過癮因此就寫下來了。排版不太好勿見怪。大神路過若有些其餘見解能夠在下面留言。