JSONP跨域模擬百度搜索
一、什么是JSONP
JSONP是JSON with padding(填充式JSON或參數(shù)式JSON)的簡寫,是應(yīng)用JSON的一種新方法,在后來的Web服務(wù)中非常流行,JSONP看起來與JSON差不多,只不過是被包含在函數(shù)中調(diào)用的JSON,就像下面這樣:
callback({"name": "王歡"});
SONP由兩部分組成:回調(diào)函數(shù)和數(shù)據(jù)?;卣{(diào)函數(shù)是當(dāng)響應(yīng)到來時(shí)應(yīng)該在頁面 中調(diào)用的函數(shù)。回調(diào)函數(shù)的名字一般是在請求中指定的。而數(shù)據(jù)就是傳入回調(diào)函數(shù)中的JSON數(shù)據(jù)。下面就是一個(gè)典型的JSONP請求。
https://freegeoip.net/json/?callback=handleResponse
這個(gè)URL是在請求一個(gè)JSONP地理定位服務(wù),通過查詢字符串來指定JSONP服務(wù)的回調(diào)參數(shù)是很常見的,就像上面的URL所示,這里指定的回調(diào)函數(shù)的名字叫做:handleResponse()
JSONP是通過動(dòng)態(tài)<script>元素來使用的,使用時(shí)可以為src屬性指定一個(gè)跨域URL??梢圆皇芟拗频膹钠渌蚣虞d資源,因?yàn)镴SONP是有效的JavaScript代碼,所以在請求完成后,即在JSONP響應(yīng)加載到頁面中以后,就會(huì)立即執(zhí)行。
二、JSONP跨域請求
我們知道,同源策略是瀏覽器的一種安全機(jī)制,所謂的源是指協(xié)議、域名和端口號,當(dāng)我們的腳本在運(yùn)行時(shí),瀏覽器會(huì)檢測它所執(zhí)行的腳本和他所取得的的數(shù)據(jù)與我們HTML頁面是否相同,如果相同,就是同源的,會(huì)進(jìn)行成功的請求,如果他們的源不相同,就是跨域請求。在默認(rèn)情況下,瀏覽器是不支持跨域請求的,那么如果我們想要跨域請求,該如何操作呢?
script標(biāo)簽是不受同源策略的限制的,即我們在請求script腳本的時(shí)候,無論是在HTML所在的服務(wù)器還是其他服務(wù)器,它都可以請求到,所以我們就利用script標(biāo)簽的這種性質(zhì)來進(jìn)行數(shù)據(jù)的跨域請求。就來看看JSONP是如何進(jìn)行跨域請求的。
首先,我們請求一段script代碼,這段代碼里如果它能調(diào)用我們所指定的一個(gè)函數(shù),并將數(shù)據(jù)作為實(shí)參傳遞進(jìn)來,那么只要我們定義了這個(gè)函數(shù)并定義了形參,形參就會(huì)接收到他的實(shí)參來得到數(shù)據(jù)。舉個(gè)例子:
假設(shè)在腳本中定義了一個(gè)getData(data) ,如果現(xiàn)在請求一個(gè)腳本,這個(gè)腳本能夠調(diào)用getData()這個(gè)函數(shù),并將data 作為實(shí)參傳遞進(jìn)來,那形參收到的數(shù)據(jù)就可以進(jìn)行相應(yīng)的處理。
<script>
function getData(data){
console.log(data);
}
var script = document.createElement('script');
script.id = 'jsonp';
script.src = 'jsonp.js';
document.body.appendChild(script);
</script>
假設(shè)前端已經(jīng)把函數(shù)名告訴了后端,后端就可以調(diào)用這個(gè)getData() ,并且可以傳遞信息。在jsonp.html就可以請求到下述jsonp.js文件。
getData({
name: '小王',
age: 20
})
運(yùn)行得到結(jié)果為:

得到了一個(gè)Object對象,就是我們所傳遞的數(shù)據(jù)。
那么,我們?nèi)绾胃嬖V服務(wù)器getData()這個(gè)函數(shù)呢?如果我們每次都固定是getData(),我們的開發(fā)會(huì)很死板,就不能定義其他函數(shù)名字。實(shí)際上,我們可以通過get請求將我們前端定義的函數(shù)名字通過參數(shù)告訴后端,后端動(dòng)態(tài)生成這樣的一個(gè)腳本文件并返回給函數(shù)的調(diào)用就可以。
百度就有一個(gè)這樣的接口,我們一起來看看。
打開瀏覽器百度頁面,打開調(diào)試工具,看一下NETwork標(biāo)簽下面會(huì)監(jiān)聽所有關(guān)于瀏覽器向服務(wù)器發(fā)送的http請求并查看數(shù)據(jù)。
在搜索框鍵入“b”,請求如圖:

請求得到的關(guān)鍵字為:

這里的callback函數(shù)其實(shí)是jquery生成的一個(gè)全局函數(shù)。得到這個(gè)URL后,我們可以保存其有用的信息,并將回調(diào)函數(shù)換成別的函數(shù):
https://www.baidu.com/sugrec?pre=1&wd=b&req=2&csor=1&cb=getData();
將其輸入到地址欄中進(jìn)行測試:

可以發(fā)現(xiàn),這個(gè)回調(diào)函數(shù)就變成了我們設(shè)置的。
三、模擬百度搜索
我們現(xiàn)在就可以通過這個(gè)接口去發(fā)生JSON來模擬一下百度搜索頁面。
我們定義一個(gè)全局變量作為接收數(shù)據(jù)的函數(shù),data就是接收到的數(shù)據(jù),一旦getdata()函數(shù)被調(diào)用,說明我們我們的Jsonp函數(shù)就發(fā)送完成,此時(shí)可以通過removeChild()刪除script標(biāo)簽,這樣就可以實(shí)現(xiàn)每當(dāng)我們發(fā)送一次請求,script標(biāo)簽在接收到數(shù)據(jù)后就會(huì)被刪除,在數(shù)據(jù)處理的時(shí)候,getData()返回給我們的是一個(gè)對象,對象里面有一個(gè)關(guān)鍵字g,里面對應(yīng)的是一個(gè)數(shù)組,數(shù)組里面是字符串,我們先將這個(gè)數(shù)組遍歷,然后根據(jù)每個(gè)元素生成一個(gè)li加到input下面的ul就可以,先將ul里面的html清空,這樣的話,每次請求的li都是全新的,當(dāng)keyup出來的時(shí)候,首先取到當(dāng)前input的value值并調(diào)用getdata()函數(shù),將wd傳進(jìn)來,就實(shí)現(xiàn)了jsonp傳遞數(shù)據(jù)的過程。
代碼如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
div {
position: relative;
width: 600px;
height: 40px;
}
input {
width: 500px;
height: 40px;
border: 2px solid #4E6EF2;
}
button{
position: absolute;
left: 411px;
top: 0;
width: 95px;
height: 44px;
background-color: #4E6EF2;
border: none;
font-size: 18px;
color: white;
}
ul{
position: relative;
left: -40px;
top: -10px;
width: 411px;
height: 400px;
}
li{
height: 40px;
width: 411px;
line-height: 40px;
font-size: 16px;
list-style: none;
}
</style>
</head>
<body>
<div>
<input type="text" value =''>
<button>百度一下</button>
</div>
<ul></ul>
<script src="jquery.js"></script>
<script>
//
function getData(data){
var script = document.querySelector('#jsonp');
script.parentNode.removeChild(script);
$('ul').html('');
for(var i =0;i<data.g.length;i++){
$('<li>'+data.g[i].q +'</li>').appendTo('ul');
}
}
//動(dòng)態(tài)生成script腳本
function getList(wd){
var script = document.createElement('script');
script.id = 'jsonp';
script.src = 'https://www.baidu.com/sugrec?pre=1&p=3&ie=utf-8&json=1&prod=pc&from=pc_web&sugsid=26350&req=2&csor=1&cb=getData&wd='+wd;
document.body.appendChild(script);
}
//給
var ipt = document.querySelector('input');
ipt.addEventListener('keyup',function(){
var wd = this.value;
getList(wd);
console.log(wd);
})
</script>
</body>
</html>
效果為:

四、JSONP缺點(diǎn)
JSONP之所以在開發(fā)人員中極為流行,是因?yàn)樗浅:唵我子?,不過他也有兩點(diǎn)不足:
- 首先,
JSONP是從其他域中加載執(zhí)行代碼。如果其他域不安全,很可能會(huì)在響應(yīng)中夾帶一些惡意代碼,而此時(shí)除了完全放棄JSONP調(diào)用之外,沒有辦法追究。 其次,要確定JSONP請求是否失敗并不容易。雖然HTML5給<script>元素新增了一個(gè)onerror事件處理程序,但目前還沒有得到任何瀏覽器的支持。為此,開發(fā)人員不得不使用計(jì)時(shí)器檢測指定時(shí)間內(nèi)是否接收到了響應(yīng)。但是畢竟不是每個(gè)用戶的上網(wǎng)速度和帶寬都一樣,所以操作起來也不盡人意。
到此這篇關(guān)于JSONP跨域模擬百度搜索的文章就介紹到這了,更多相關(guān)JSONP跨域模擬百度搜索內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
微信小程序動(dòng)態(tài)評分展示/五角星展示/半顆星展示/自定義長度展示功能的實(shí)現(xiàn)
這篇文章主要介紹了微信小程序動(dòng)態(tài)評分展示/五角星展示/半顆星展示/自定義長度展示的實(shí)現(xiàn),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-07-07
使用JS輕松實(shí)現(xiàn)ionic調(diào)用鍵盤搜索功能(超實(shí)用)
這篇文章主要介紹了使用JS輕松實(shí)現(xiàn)ionic調(diào)用鍵盤搜索功能(超實(shí)用)的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-09-09
js實(shí)現(xiàn)prototype擴(kuò)展的方法(字符串,日期,數(shù)組擴(kuò)展)
這篇文章主要介紹了js實(shí)現(xiàn)prototype擴(kuò)展的方法,實(shí)例分析了JavaScript針對字符串、日期、數(shù)組等的prototype擴(kuò)展相關(guān)技巧,需要的朋友可以參考下2016-01-01
微信小程序動(dòng)態(tài)生成二維碼的實(shí)現(xiàn)代碼
這篇文章主要介紹了微信小程序動(dòng)態(tài)生成二維碼的實(shí)現(xiàn)代碼,需要的朋友可以參考下2018-07-07
原生js實(shí)現(xiàn)隨機(jī)點(diǎn)名功能
這篇文章主要為大家詳細(xì)介紹了原生js實(shí)現(xiàn)隨機(jī)點(diǎn)名功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-11-11
uniapp中uni.navigateBack返回后刷新頁面數(shù)據(jù)的實(shí)現(xiàn)
本文主要介紹了uniapp中uni.navigateBack返回后刷新頁面數(shù)據(jù)的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-11-11
js window.onload 加載多個(gè)函數(shù)的方法
平時(shí)做項(xiàng)目 經(jīng)常需要使用window.onload,但window.onload 不能同時(shí)加載多個(gè)函數(shù)。2009-11-11
JavaScript跨瀏覽器獲取頁面中相同class節(jié)點(diǎn)的方法
這篇文章主要介紹了JavaScript跨瀏覽器獲取頁面中相同class節(jié)點(diǎn)的方法,本文講解使用getELementsByClassName函數(shù)解決這個(gè)需求,并給了一個(gè)開源的getELementsByClassName函數(shù)實(shí)現(xiàn),功能更加強(qiáng)大,需要的朋友可以參考下2015-03-03
JavaScript實(shí)現(xiàn)字符串與HTML格式相互轉(zhuǎn)換
這篇文章主要介紹了JavaScript實(shí)現(xiàn)字符串與HTML格式相互轉(zhuǎn)換,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-03-03

