1. 程式人生 > >前端跨域解決辦法之JSONP

前端跨域解決辦法之JSONP

由於JavaScript的同源策略限制,在當前JavaScript指令碼中並不能操作來自非同一域下的資源,這就使得跨域問題之於前端工程師就像彈吉他之於民謠歌手——是非常重要的基本功。

跨域問題解決辦法有很多種,比如W3C給出的CORS(Cross-Origin Resource Sharing,跨源資源共享),它的基本思想就是使用自定義的HTTP頭部讓瀏覽器與伺服器進行溝通,從而決定請求或響應是應該成功還是失敗;又比如以本域下的後端伺服器做代理轉發請求,從而獲得資源來供給本域下的JavaScript使用;以上,都不是我想說的重點,重點是我想說一下JSONP。

JavaScript雖然受同源策略影響,但是script標籤載入資源並不會被它限制。JSONP就是利用這一點進行跨域資源請求,在資源載入進來之前定義好一個函式,這個函式接收一個引數(資料),函式裡面利用這個引數做一些事情然後需要的時候通過script標籤載入對應遠端檔案資源,當遠端的檔案資源被載入進來的時候,就會去執行我們前面定義好的函式,並且把資料當作這個函式的引數傳入進去。即,JSON with Padding,載入進來的資源一般是以json形式存在的,而這些資源被當做引數傳遞給回撥函式。

擼程式碼:

<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>無標題文件</title>

<script>
function fn(data) {
	var oUl1 = document.getElementById('ul1');
	var html = '';

	for (var i=0; i<data.length; i++) {
		html += '<li>'+data[i]+'</li>';
	}
	oUl1.innerHTML = html;
}
window.onload = function() {
	
	var oBtn1 = document.getElementById('btn1');
	
	oBtn1.onclick = function() {
		
		var oScript = document.createElement('script');
		oScript.src = 'getData.php';
		document.body.appendChild(oScript);
	}
}
</script>
</head>

<body>
<span style="white-space:pre">	</span><input type="button" id="btn1" value="按鈕" />
    <span style="white-space:pre">	</span><ul id="ul1"></ul>
</body>
</html>

以下是被呼叫的php檔案:
<?php
$t = isset($_GET['t']) ? $_GET['t'] : 'num';
$callback = isset($_GET['callback']) ? $_GET['callback'] : 'fn';

$arr1 = array('111111','22222222','33333333','4444444','555555555555555555555');
$arr2 = array('aaaaaaaaaaaa','bbbbbbbb','cccccccccccc','ddddddddd','eeeeeeeeeeee');

if ($t == 'num') {
	$data = json_encode($arr1);
} else {
	$data = json_encode($arr2);
}

echo $callback.'('.$data.');';
可以看到,在php中以函式呼叫的形式輸出,並將引數傳入,這樣即使php檔案不在同一個域下,前端的JavaScript也能請求到,並且利用已經宣告的函式進行呼叫。我們還可以將script的src屬性改為有引數的形式:'getData.php?t=str',這樣可以得到另外的資源。

同樣的道理,我們還可以做一些更復雜豐富的應用。比如利用一些入口網站給出的api介面可以呼叫他們資料庫裡的資源,去完成我們想實現的各種功能,以後有機會再接著聊這個話題。