什么是跨域?
简单的来说,出于安全方面的考虑,页面中的JavaScript无法访问其他服务器上的数据,即“同源策略”。而跨域就是通过某些手段来绕过同源策略限制,实现不同服务器之间通信的效果。
具体策略限制情况可看下表:
URL | 说明 | 允许通信 |
http://www.a.com/a.js http://www.a.com/b.js |
同一域名下 | 允许 |
http://www.a.com/lab/a.js http://www.a.com/script/b.js |
同一域名下不同文件夹 | 允许 |
http://www.a.com:8000/a.js http://www.a.com/b.js |
同一域名,不同端口 | 不允许 |
http://www.a.com/a.js https://www.a.com/b.js |
同一域名,不同协议 | 不允许 |
http://www.a.com/a.js http://127.0.0.100/b.js |
域名和域名对应ip | 不允许 |
http://www.a.com/a.js http://script.a.com/b.js |
主域相同,子域不同 | 不允许 |
http://www.a.com/a.js http://a.com/b.js |
同一域名,不同二级域名(同上) | 不允许 |
http://www.a.com/a.js http://www.b.com/b.js |
不同域名 | 不允许 |
什么是JSONP?
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,而JSONP(JSON with Padding)则是JSON 的一种“使用模式”,通过这种模式可以实现数据的跨域获取。
JSONP跨域的原理
在同源策略下,在某个服务器下的页面是无法获取到该服务器以外的数据的,但img、iframe、script等标签是个例外,这些标签可以通过src属性请求到其他服务器上的数据。利用script标签的开放策略,我们可以实现跨域请求数据,当然,也需要服务端的配合。当我们正常地请求一个JSON数据的时候,服务端返回的是一串JSON类型的数据,而我们使用JSONP模式来请求数据的时候,服务端返回的是一段可执行的JavaScript代码。
最简单的例子:
下面演示用mm.html来加载test.txt文件中的数据。test.txt模拟跨域要取的数据文件,mm.html模拟现在要渲染的页面。
test.txt中的数据格式为:
fun(
{
"result" : [
{
"xingming":"小明",
"nianling" : 12,
"sex" : "男"
},
{
"xingming":"小红",
"nianling" : 13,
"sex" : "女"
},
{
"xingming":"小绿",
"nianling" : 9,
"sex" : "女"
}
]
}
);
mm.html中代码为:
控制台能显示获取到的数据:
。。。。。。。。。。。。。最简单的例子完工,我表述不清,大家可以自行复制代码运行理解下。。。。。。。
代码如下:
function myjsonp(URL,callback,callbackname){
//给系统中创建一个全局变量,叫做callbackname,指向callback函数
//定义
window[callbackname] = callback;
//创建一个script节点
var oscript = document.createElement("script");
//和image不一样,设置src并不会发出HTTP请求
oscript.src = URL;
oscript.type = "text/javascript";
//script标签的请求是在上树的时候发出,请求的是一个函数的执行语句
document.head.appendChild(oscript);
//为了不污染页面,瞬间把script拿掉
document.head.removeChild(oscript);
}
//使用
myjsonp("http://sclub.jd.com/productpage/p-1217508-s-0-t-3-p-1.html?callback=abcdefg",function(data){
console.log(data);
},"abcdefg");
(代码中请求数据的地址http://sclub.jd.com/productpage/p-1217508-s-0-t-3-p-1.html?callback=abcdefg是在jd某个商品评价列表页面network中扒到的,请求返回的数据格式如下图,大家有兴趣可以去各种网站扒,但是记住得到的数据格式一定要是一个函数的执行并以数据为实参的url地址)
$.ajax("test.txt",{
//JSON跨域的时候要写一个dataType,注意不是type而是dataType
"dataType" : "jsonp",
//要定义的函数名字,因为JSONP不缺执行,缺定义
"jsonpCallback" : "fun",
//信息回来之后执行的事情
"success" : function(data){
console.log(data); //这里得到了请求的数据
}
});
test.txt格式为:
fun(
{
"result" : [
{
"xingming":"小明",
"nianling" : 12,
"sex" : "男"
},
{
"xingming":"小红",
"nianling" : 13,
"sex" : "女"
},
{
"xingming":"小绿",
"nianling" : 9,
"sex" : "女"
}
]
}
);
最后一种就是jq封装好的jsonp(但是这个请求走了浏览器控制面板的network的xhr,感兴趣的可以看下jq源码,看他是如何封装的),之前讲的原理懂得了,这个jq的jsonp的用法记住就好了。