什么是跨域?就不说了,一搜一大堆。
就讲讲如何跨域,本文对一些前辈的博客进行总结精简,尽量简洁的表述粗来。
一、CORS
是W3C制定的为解决跨域请求的一个规范。直接上代码
var xhr = new XMLHttpRequest();
xhr.open("GET", "http://www.a.com",true);
xhr.send();
其实很简单,即发送请求时,请求头中有一个"origin:http://www.b.com."
服务器响应头中返回"Access-Control-Allow-Origin:http://www.b.com 或 *"
"Access-Control-Request-Method":"PUT,POST"
即表示跨域请求允许,请求成功。
如果在回应的头信息中没有"Access-Control-Allow-Origin"字段则会报错,请求失败。
优点:支持所有请求方式;方式简单。
缺点:低级古老的浏览器不支持。
二、服务器代理请求
顾名思义,就是首先请求同域服务器,给同域服务器代理脚本,由代理脚本来完成跨域请求然后把结果返回客户端。
优点:支持GET和POST
缺点:处理复杂
三、JSONP方式
<script type="text/javascript">
function callFunc(data){
//处理获得的json数据
console.log(data);
}
</script>
<script src="http://example.com/data.php?callback=callFunc"></script>
<script type="text/javascript">
function callFunc(data){
//处理获得的json数据
console.log(data);
}
</script>
<script src="http://example.com/data.php?callback=callFunc"></script>
因为src的url是一个后台脚本访问后会被执行,返回的JSON以字符串形式包含在回调函数中,
返回的字符串放入script标签中则执行回调函数,返回的JSON数据也作为实参传入了回调函数。
以上应该算是比较常见的JSONP的原生实现方法,也有一些对此做了封装的框架,比如jquery如下:
$.ajax({
type : "GET",
url : "http://zhangzhanyu.nfreehost.com/jsonp.php",
dataType : "jsonp",
success : function(json) {
alert(json.msg);
}
});
请千万不要被jquery对JSONP的封装为$.ajax就误以为JSONP的跨域访问也是AJAX请求,其实两者一点关系都没有!!
我从一篇文章中看到过有人推荐的一种插件(fetch-jsonp)
fetchJsonp(Url)
.then(response => {return response.json();})
.then(json => {resolve(json);})
.catch(err => {reject({errMsg: '调用接口失败', success: false});})
利用script标签支持跨域的特性,实现跨域请求。
优点:古老的浏览器也支持
缺点:仅支持GET
四、利用iframe完成跨域请求
举个栗子,父页面(http://a.test.com/a.html)中嵌入iframe子页面(http://b.test.com/b.html)
父页面(http://a.test.com/a.html)代码:
<iframe id = "iframe" src="http://b.test.com/b.html" onload = "loadIframeData()"></iframe>
发送数据:
A(父页面) -> B(iframe):
document.getElementById('iframeId').contentWindow.postMessage(JSON.stringify(data), '*');
第一个参数传递的数据json化,第二个指定允许接收的域名,*表示允许任意域名
B(iframe )-> A(父页面):
window.parent.postMessage(JSON.stringify(data), '*');
父子页面监听接收数据
if (window.addEventListener) {
window.addEventListener('message', function(event) {
if(event.origin == '父页面url'){
try {
const data = JSON.parse(event.data);
} catch(e) {
}
}, false);
}else{
window.attachEvent('onmessage',funtion(event){
if(event.origin == '父页面url'){
try {
const data = JSON.parse(event.data);
} catch(e) {
}
}, false);
}
优点:通过iframe去完成跨域有其最显著的优势,就是在A页面向B服务器去进行跨域请求时,B服务器需要进行比较多的处理才能返回结果的时候,利用iframe去完成是非常好用的。缺点:如果iframe页面中有页面跳转的情况下,用户想回退父页面出现的结果是iframe页面回退了,但父页面URL和页面都没发生变化(需要在跳转前remove当然iframe,然后重新插入iframe到新的src,防止污染父页面url)。另外这样的做法有时候像多了一层代理,因此一方需求改动,则需要更改比较多的地方。