方法一:JSONP
原理
JSONP(JSON with padding)淮椰,padding有填補(bǔ)的意思槐沼,所以JSONP也就是往JSON上加一些東西。在HTML 中 script 標(biāo)簽可以加載其他域下的js,比如我們經(jīng)常引入一個(gè)其他域下線上cdn的jQuery。那么我們可以利用這個(gè)特性來向其他域請求數(shù)據(jù)冈欢。
對于HTML中的script標(biāo)簽,src中請求的數(shù)據(jù)返回后會被當(dāng)做Javascript代碼來運(yùn)行盈简,所以當(dāng)后臺返回?cái)?shù)據(jù)的時(shí)候凑耻,不能直接返回?cái)?shù)組或者字符串之類的,應(yīng)該對數(shù)據(jù)進(jìn)行“包裹”送火,也就是JSONP中的P代表的padding拳话,加點(diǎn)東西。下面請看例子种吸。
舉例
第一步
我們現(xiàn)在向后臺的約定了一個(gè)獲取天氣的接口getWeather
弃衍,然后在script標(biāo)簽中寫一個(gè)這樣的請求:
<script src="a.com/getWeather?callback=showData"></script>
第二步
后臺收到/getWeather
這個(gè)路由后,應(yīng)該是直接向我返回一個(gè)JSON格式的數(shù)據(jù)坚俗,其中包含天氣镜盯,比如這個(gè)數(shù)據(jù),{ "beijing" : "sunny" }
猖败。但對于script標(biāo)簽速缆,返回的數(shù)據(jù)是要作為Javascript代碼執(zhí)行的,上面返回的數(shù)據(jù)應(yīng)該進(jìn)行“包裹”恩闻,例如變成這樣showData( { "beijing" : "sunny" } )
艺糜,服務(wù)器端寫法如下:
var http = require('http');
var url = require('url');
var fs = require('fs');
var path = require('path');
var server = http.createServer(function(req,res){
var pathObj = url.parse(req.url,true);
//處理getWeather請求
if(pathObj.pathname === '/getWeather'){
var callback = pathObj.query.callback
console.log(callback)
res.write(`${callback}({"beijing":"sunny"})`)
res.end()
}else{
res.end()
}
})
server.listen(8080);
結(jié)果
方法二:CORS
原理
CORS 全稱是跨域資源共享(Cross-Origin Resource Sharing),是一種 ajax 跨域請求資源的方式幢尚,支持現(xiàn)代瀏覽器破停,IE支持10以上。 實(shí)現(xiàn)方式很簡單尉剩,當(dāng)你使用 XMLHttpRequest 發(fā)送請求時(shí)真慢,瀏覽器發(fā)現(xiàn)該請求不符合同源策略,會給該請求加一個(gè)請求頭:Origin理茎,Origin對應(yīng)的值是當(dāng)前網(wǎng)站的域名黑界。后臺進(jìn)行一系列處理,如果確定接受請求則在返回結(jié)果中加入一個(gè)響應(yīng)頭:Access-Control-Allow-Origin皂林; 瀏覽器判斷該響應(yīng)頭中是否包含 Origin 的值(也就是Access-Control-Allow-Origin的值和Origin的值對應(yīng))朗鸠,如果有則瀏覽器會處理響應(yīng),我們就可以拿到響應(yīng)數(shù)據(jù)础倍,如果不包含童社,瀏覽器直接駁回,這時(shí)我們無法拿到響應(yīng)數(shù)據(jù)著隆。所以 CORS 的表象是讓你覺得它與同源的 ajax 請求沒啥區(qū)別扰楼,代碼完全一樣呀癣。
舉例
- HTML代碼
//打開此頁面使用的地址是a.com:8080
<!DOCTYPE html>
<html>
<head>
<title>a.html</title>
<meta charset="utf-8">
</head>
<body>
<button id="click">發(fā)送請求</button>
<script type="text/javascript">
click.onclick = function(){
var xhr = new XMLHttpRequest()
xhr.open('GET', 'http://b.com:8080/getWeather')
xhr.onload = function(){
console.log(xhr.responseText)
}
xhr.send()
}
</script>
</body>
</html>
- 服務(wù)端代碼
var http = require('http');
var url = require('url');
var fs = require('fs');
var path = require('path');
var server = http.createServer(function(req,res){
var pathObj = url.parse(req.url,true);
//處理getWeather請求
if(pathObj.pathname === '/getWeather'){
var weather = {"beijing":"sunny"}
res.setHeader('Access-Control-Allow-Origin', 'http://a.com:8080')
res.write(JSON.stringify(weather))
res.end()
}else{
res.end()
}
})
server.listen(8080);
方法三:降域
原理
主要用于頁面上iframe跨域的操作。降域就是通過在兩個(gè)頁面使用 document.domain
方法弦赖,將兩個(gè)頁面的域名統(tǒng)一项栏,由此來實(shí)現(xiàn)跨域。不過這要求兩個(gè)頁面的域名有公共的部分蹬竖。
舉例
- a.html
<!DOCTYPE html>
<html>
<head>
<title>a.html</title>
<meta charset="utf-8">
<style type="text/css">
.windowB {
height: 250px;
width: 500px;
margin: 10px 10px;
border: 1px #ccc solid;
}
</style>
</head>
<body>
<h1>this is a.html</h1>
<iframe class="windowB" src="http://b.common.com:8080/b.html"></iframe>
</body>
</html>
- b.html
<!DOCTYPE html>
<html>
<head>
<title>b.html</title>
</head>
<body>
<h1>this is b.html</h1>
<script type="text/javascript">
document.domain = 'common.com'
</script>
</body>
</html>
效果
方法四:postMessage
原理
當(dāng)前頁面要和iframe進(jìn)行數(shù)據(jù)交互的時(shí)候沼沈,可以選中需要交互的iframe,然后利用postMessage這個(gè)方法向它發(fā)送消息币厕,然后在iframe頁面上監(jiān)聽message這個(gè)事件列另,對發(fā)來的信息做處理,這樣就可以實(shí)現(xiàn)數(shù)據(jù)的交互旦装。
舉例
- a.html
<!DOCTYPE html>
<html>
<head>
<title>a.html</title>
<meta charset="utf-8">
<style type="text/css">
.windowB {
height: 250px;
width: 500px;
margin: 10px 10px;
border: 1px #ccc solid;
}
</style>
</head>
<body>
<h1>this is a.html</h1>
<button id="click">發(fā)送請求</button>
<input type="text" name="data" placeholder="請輸入文字">
<script type="text/javascript">
function $(e){
var element = document.querySelector(e)
return element
}
//選中input页衙,綁定事件,當(dāng)輸入信息時(shí)阴绢,在iframe中展示店乐,*表示在任何域下都可以接受
$('input').addEventListener('input', function(){
window.frames[0].postMessage(this.value,'*')
})
</script>
</body>
</html>
- b.html
<!DOCTYPE html>
<html>
<head>
<title>b.html</title>
<meta charset="utf-8">
</head>
<body>
<h1>this is b.html</h1>
<input type="text" name="data2" placeholder="顯示數(shù)據(jù)">
<script type="text/javascript">
function $(e){
var element = document.querySelector(e)
return element
}
window.addEventListener('message',function(e){
$('input').value = e.data
})
</script>
</body>
</html>