跨域的幾種方法
通過jsonp跨域
在js中澜倦,我們直接用XMLHttpRequest請求不同域上的數(shù)據(jù)時聚蝶,是不可以的。但是藻治,在頁面上引入不同域上的js腳本文件卻是可以的碘勉,jsonp正是利用這個特性來實現(xiàn)的。
- 可以先這樣試試:
<script src="http://api.jirengu.com/weather.php"></script>
這時候會向天氣接口發(fā)送請求獲取數(shù)據(jù)栋艳,獲取數(shù)據(jù)后做為 js 來執(zhí)行。 但這里有個問題句各, 數(shù)據(jù)是 JSON 格式的數(shù)據(jù)吸占,直接作為 JS 運行的話我如何去得到這個數(shù)據(jù)來操作呢晴叨?
- 這樣試試:
<script src="http://api.jirengu.com/weather.php?callback=showData"></script>
- 這個請求到達(dá)后端后,后端會去解析callback這個參數(shù)獲取到字符串showData矾屯,在發(fā)送數(shù)據(jù)做如下處理:
之前后端返回數(shù)據(jù): {"city": "hangzhou", "weather": "晴天"} 現(xiàn)在后端返回數(shù)據(jù): showData({"city": "hangzhou", "weather": "晴天"}) 前端script標(biāo)簽在加載數(shù)據(jù)后會把 「showData({“city”: “hangzhou”, “weather”: “晴天”})」做為 js 來執(zhí)行兼蕊,這實際上就是調(diào)用showData這個函數(shù),同時參數(shù)是 {“city”: “hangzhou”, “weather”: “晴天”}件蚕。 用戶只需要在加載提前在頁面定義好showData這個全局函數(shù)孙技,在函數(shù)內(nèi)部處理參數(shù)即可。
<script>
function showData(ret){
console.log(ret);
}
</script>
<script src="http://api.jirengu.com/weather.php?callback=showData"></script>
這就是 JSONP(JSON with padding)排作,總結(jié)一下:
JSONP是通過 script 標(biāo)簽加載數(shù)據(jù)的方式去獲取數(shù)據(jù)當(dāng)做 JS 代碼來執(zhí)行 提前在頁面上聲明一個函數(shù)牵啦,函數(shù)名通過接口傳參的方式傳給后臺,后臺解析到函數(shù)名后在原始數(shù)據(jù)上「包裹」這個函數(shù)名妄痪,發(fā)送給前端哈雏。換句話說,JSONP 需要對應(yīng)接口的后端的配合才能實現(xiàn)衫生。
- server.js
var http = require('http')
var fs = require('fs')
var path = require('path')
var url = require('url')
http.createServer(function (req, res) {
var pathObj = url.parse(req.url, true)
switch (pathObj.pathname) {
case '/getNews':
var news = [
"第11日前瞻:中國沖擊4金 博爾特再戰(zhàn)200米羽球",
"正直播柴飚/洪煒出戰(zhàn) 男雙力爭會師決賽",
"女排將死磕巴西裳瘪!郎平安排男陪練模仿對方核心"
]
res.setHeader('Content-Type', 'text/json; charset=utf-8')
if (pathObj.query.callback) {
res.end(pathObj.query.callback + '(' + JSON.stringify(news) + ')')
} else {
res.end(JSON.stringify(news))
}
break;
default:
fs.readFile(path.join(__dirname, pathObj.pathname), function (e, data) {
if (e) {
res.writeHead(404, 'not found')
res.end('<h1>404 Not Found</h1>')
} else {
res.end(data)
}
})
}
}).listen(8080)
- index.html
<!DOCTYPE html>
<html>
<body>
<div class="container">
<ul class="news">
</ul>
<button class="show">show news</button>
</div>
<script>
$('.show').addEventListener('click', function () {
var script = document.createElement('script');
script.src = 'http://127.0.0.1:8080/getNews?callback=appendHtml';
document.head.appendChild(script);
document.head.removeChild(script);
})
function appendHtml(news) {
var html = '';
for (var i = 0; i < news.length; i++) {
html += '<li>' + news[i] + '</li>';
}
console.log(html);
$('.news').innerHTML = html;
}
function $(id) {
return document.querySelector(id);
}
</script>
</html>
打開終端,輸入 node server.js 罪针,瀏覽器打開 http://localhost:8080/index.html
CORS
CORS 全稱是跨域資源共享(Cross-Origin Resource Sharing)彭羹,是一種 ajax 跨域請求資源的方式,支持現(xiàn)代瀏覽器泪酱,IE支持10以上派殷。 實現(xiàn)方式很簡單,當(dāng)你使用 XMLHttpRequest 發(fā)送請求時西篓,瀏覽器發(fā)現(xiàn)該請求不符合同源策略愈腾,會給該請求加一個請求頭:Origin,后臺進(jìn)行一系列處理岂津,如果確定接受請求則在返回結(jié)果中加入一個響應(yīng)頭:Access-Control-Allow-Origin; 瀏覽器判斷該相應(yīng)頭中是否包含 Origin 的值虱黄,如果有則瀏覽器會處理響應(yīng),我們就可以拿到響應(yīng)數(shù)據(jù)吮成,如果不包含瀏覽器直接駁回橱乱,這時我們無法拿到響應(yīng)數(shù)據(jù)。所以 CORS 的表象是讓你覺得它與同源的 ajax 請求沒啥區(qū)別粱甫,代碼完全一樣泳叠。
- server.js
var http = require('http')
var fs = require('fs')
var path = require('path')
var url = require('url')
http.createServer(function (req, res) {
var pathObj = url.parse(req.url, true)
switch (pathObj.pathname) {
case '/getNews':
var news = [
"第11日前瞻:中國沖擊4金 博爾特再戰(zhàn)200米羽球",
"正直播柴飚/洪煒出戰(zhàn) 男雙力爭會師決賽",
"女排將死磕巴西!郎平安排男陪練模仿對方核心"
]
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:8080')
//res.setHeader('Access-Control-Allow-Origin','*')
res.end(JSON.stringify(news))
break;
default:
fs.readFile(path.join(__dirname, pathObj.pathname), function (e, data) {
if (e) {
res.writeHead(404, 'not found')
res.end('<h1>404 Not Found</h1>')
} else {
res.end(data)
}
})
}
}).listen(8080)
區(qū)別在于訪問控制與允許的域,交給瀏覽器作判斷.
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:8080')
允許任何人獲得數(shù)據(jù)
res.setHeader('Access-Control-Allow-Origin','*')
- index.html
<!DOCTYPE html>
<html>
<body>
<div class="container">
<ul class="news">
</ul>
<button class="show">show news</button>
</div>
<script>
$('.show').addEventListener('click', function () {
var xhr = new XMLHttpRequest()
xhr.open('GET', 'http://127.0.0.1:8080/getNews', true)
xhr.send()
xhr.onload = function () {
appendHtml(JSON.parse(xhr.responseText))
}
})
function appendHtml(news) {
var html = ''
for (var i = 0; i < news.length; i++) {
html += '<li>' + news[i] + '</li>'
}
$('.news').innerHTML = html
}
function $(selector) {
return document.querySelector(selector)
}
</script>
</html>