一、JSONP
我们都知道script标签src属性中的链接却可以访问跨域的js脚本,利用这个特性,服务端不再返回JSON格式的数据,而是返回一段调用某个函数的js代码,在src中进行了调用函数来获取到数据,函数中的参数就是我们需要的数据,这样实现了跨域。
基本思想是:
1、客户端利用script标签可以跨域请求资源的性质,向网页中动态插入script标签,来向服务端请求数据。
2、服务端会解析请求的url,至少拿到一个回调函数(比如callback=myCallback)参数,之后将数据当做函数参数
放入其中返回给客户端。
3、当然jsonp仅支持get类型的方式
下面我们将举例说明:
需要跨域请求的地址是:
https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=hello&sugmode=2&json=1&p=3&sid=1449_21106_27377&req=2&bs=hello&pbs=hello&csor=5&pwd=hello&cb=jQuery110203960180958059971_1542965283806&_=1542965283817
1、原生js方式实现jsonp
<!-- 我们来抓取百度搜索的接口数据(在文章发布时我测试过能正常访问,如果之后接口有改版请自行找其他接口测试) -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>jsonp</title>
<script>
//jsonhandle函数名要和请求的callback参数名一致,在这里是url参数中的cb=jsonhandle
function jsonhandle(data){ //请求到接口后返回的数据就在这里进行处理
console.log(data);
}
</script>
<script type="text/javascript">
window.onload = function(){
var body = document.body;
var oInput = document.getElementById("search");
var oBtn = document.getElementById("btn");
//点击按钮之后才动态添加script标签进行jsonp请求
oBtn.onclick = function(){
var text = oInput.value;
//wd参数是搜索的关键字,我们可以动态改变,进行字符串拼接即可
var url = "https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd="+text+"&sugmode=2&json=1&p=3&sid=1449_21106_27377&req=2&bs=hello&pbs=hello&csor=5&pwd=hello&cb=jsonhandle&_=1542965283817";
var scriptDom = document.createElement("script");
scriptDom.src = url;
body.appendChild(scriptDom);
};
}
</script>
</head>
<body>
<div class="wrap">
<input type="text" placeholder="百度一下你就知道" id="search" autocomplete="off">
<input type="button" value="百度" id="btn">
</div>
</body>
</html>
其实原理就是:我们在输入框输入了关键字之后,点击按钮就会在页面中动态添加了一个script标签,这个标签就是去请求接口的,然后返回来的数据格式是jsonhandle("请求到的数据作为了函数的参数")
,这里就相当于函数jsonhandle被调用,然后我们之前在上面定义了函数function jsonhandle(data){ }在此时就被调用了,那么参数data就是获取到的数据,这时候就可以在定义的函数中进行数据处理了。
2、jquery提供的便捷式方式实现jsonp
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>jsonp</title>
<!-- 引入jquery的cdn -->
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script type="text/javascript">
$(function(){
//点击按钮后才进行jsonp跨域请求
$("#btn").click(function(){
var text = $("#search").val();
$.ajax({
type : "get",
url : "https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd="+text+"&sugmode=2&json=1&p=3&sid=1449_21106_27377&req=2&bs=hello&pbs=hello&csor=5&pwd=hello&_=1542965283817",
dataType: "jsonp",
jsonp:"cb", //请求回调函数的参数名,如cb=jsonhandle,这里就需要写cb
jsonpCallback: "jsonhandle",//要执行的回调函数名(自定义)
success : function(data) { //这里就是请求接口后得到的数据,在这个函数进行数据处理
console.log(data)
}
});
})
});
</script>
</head>
<body>
<div class="wrap">
<input type="text" placeholder="百度一下你就知道" id="search" autocomplete="off">
<input type="button" value="百度" id="btn">
</div>
</body>
</html>
二、hash
原理是利用location.hash来进行传值。在url: http://a.com#hello中的"#hello"就是location.hash,改变hash并不会导致页面刷新,所以可以利用hash值来进行数据传递,当然数据容量是有限的(就和get请求一样,参数长度有限制)。
//利用hash的场景是,当页面A通过iframe嵌入了跨域的页面B
//在页面A中的伪代码如下:
var Biframe = document.getElementByTagName("iframe");
Biframe.src = Biframe.src + "#" + 'datas' //这里的datas可以是json类型的字符串,就是要传给B页面的数据
//在页面B中的伪代码如下:
window.onhashchange = function(){
var data = window.location.hash; // 这里获取到B页面url地址#号后面的所有数据
}
三、postMessage
HTML5新增的解决跨域的知识点。
postMessage()方法允许来自不同源的脚本采用异步方式进行有限的通信,可以实现跨文本档、多窗口、跨域消息传递。
参考帖子:https://blog.csdn.net/m0_38134431/article/details/83344894
四、WebSocket
不受同源限制,所以就能进行跨域请求了。
五、CORS
支持跨域通信的ajax。在使用ajax发送请求的时候在请求头中加入一个origin来允许跨域通信。
CORS是一个W3C标准,全称是"跨域资源共享
"(Cross-origin resource sharing)。
它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。
上面的代码是同源请求方式、如果需要跨域就要配置相应请求头。
CORS原理参考网址:http://www.ruanyifeng.com/blog/2016/04/cors.html
CORS跨域使用Fetch API (ES6的知识点)
Fetch API原帖子:https://www.jianshu.com/p/35123b048e5e