JavaScript:使用原生JS實現Jsonp跨域,呼叫百度搜索介面完成聯想詞功能
阿新 • • 發佈:2018-12-15
Jsonp解釋
Jsonp這個術語聽起來很高大上,其實它的原理非常簡單,就是利用src不受同源策略限制這一點來實現的,很多標籤都有src特性。
你們可以想想為什麼img標籤能將不同源的百度logo拿過來?
<img src="https://www.baidu.com/img/bd_logo1.png" alt="">
Jsonp原理
一、src不受同源策略的限制,不受跨域的影響,所以可以藉助script中的src屬性進行跨域獲取資料。
二、所以將資料放到伺服器上,並且資料為json形式,因為js可以輕鬆處理json資料。
三、由於我們動態建立的script標籤是一個非同步載入的過程,不確定資料什麼時候回來,所以要做個處理,在前端寫好一個function並將函式名傳給伺服器,後端拿到函式名,完成一個拼接 functionName(parameter),將json資料以入參的方式放置在function中,生成js語法的文件,返回給客戶端。此時客戶端繼續解析,將json資料作為引數,傳入之前定義好的callback函式中。
四、所以根據第三步,需要先寫好函式來處理跨域獲取的資料。
五、用src獲取資料的時候,在url後邊新增一個引數,例如cb = xxx,服務端會將cb的值,對應為一個函式,將引數插入到其中,例如 xxx(parameter)
注意
基於JSONP的實現原理,所以JSONP只能是“GET”請求,不能進行較為複雜的POST和其它請求,所以遇到那種情況,就得參考CORS解決跨域了(所以如今它也基本被淘汰了)。
下面程式碼演示如何使用Jsonp來實現跨域請求百度搜索介面,完成聯想詞功能,這裡先用原生JS來實現,能更好理解實現原理。在jQuery的ajax裡封裝了Jsonp和CORS跨域解決辦法,後期會進行講解。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>百度搜索框</title>
<style>
*{
padding: 0;
margin: 0;
list-style: none;
}
input{
width: 400px;
height : 34px;
}
ul{
display: none;
width: 400px;
border: 1px solid #ccc;
}
li{
margin-left: 10px;
margin-top: 3px;
}
.wrapper{
margin: 100px;
}
a{
text-decoration: none;
color: #666;
font-size: 14px;
}
</style>
</head>
<body>
<div class="wrapper">
<input type="text">
<ul>
</ul>
</div>
<script src="jquery.js"></script>
<script>
function ds(data) {
console.log(data)
}
/*通過jsonp訪問百度伺服器,獲取搜尋聯想詞*/
var oInput = document.getElementsByTagName("input")[0];
oInput.oninput = function () {
var value = this.value;
var oScript = document.createElement("script");
//wd=關鍵字,doJson=執行函式名,這裡要保證傳的是函式名的字串!!!
oScript.src = "https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd="+ value +"&cb=doJson&_=1544270132010";
//這裡將插入以聯想詞陣列為引數的名為doJson的js檔案,馬上執行
document.body.appendChild(oScript);
//執行完以後又馬上移除掉
document.body.removeChild(oScript);
};
function doJson(data) {
var s = data.s;
$("ul").empty();
//當輸入值過多時,s的聯想詞會匹配不到
if(s.length > 0){
s.forEach(function (ele,index) {
var a = $("<a></a>").attr("href","https://www.baidu.com/s?wd=" + ele);
a.text(ele);
$("<li></li>").append(a).appendTo($("ul"));
});
$("ul").css("display","block");
}else{
$("ul").css("display","none");
}
}
</script>
</body>
</html>