跨域(同源策略)
scr href 两个可以跨域的属性
<!-- 跨域获取数据 -->
<!-- 同源策略:域名,协议,端口均相同
跨域:从一个域名的网页去请求另一个域名的资源,严格意义的定义是:只要域名,协议,端口有一个不同,就是跨域。
如何解决跨域:
1,跨域资源共享(CORS)
2,使用JSONP(常用,就是填充式JSON)
3,修改document.domain
4,使用window.name
下面是JSONP的介绍
1,什么JSONP是JSON with Padding(填充式json)的简写,是应用JSON的一种新方法,也是一种跨域解决方案。
2,JSONP 由两部分组成:回调函数 和 数据。
回调函数:当响应到来时应该在页面中调用的函数
数据:是传入回调函数中JSON数据
JSONP原理:
1,通过script标签引入js文件
2,js文件加载成功后
3,执行我们在url参数中指定的函数
直接使用XMLHttpRequest请求不同域上的数据时,是不可以的,
但是,在页面上引入不同域上的js脚本文件却是可以的。 -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>跨域</title>
</head>
<body>
<script>
//使用src属性可以跨域的特性,进行的一种跨域获取数据的做法:
//1,封装JSONP跨域函数,两个参数:url,callback
// url:需要获得数据的不同域名,协议,端口号的地址
// callback:回调函数用于处理服务器返回的数据dat
//2,处理url,判断是否有效,如有效,则给url添加一个自定义的函数,
// 用于接收服务器返回的数据data,
// 如:https://www.baidu.com?id=234&jsonp=getJSONP.abcd
// jsonp可以随便定义,只是过渡作用
// getJSONP.abcd :给getJSONP对象添加abcd属性,该属性是一个函数如:
// getJSONP.abcd=function(data){...},只要abcd是一个函数,
// 服务器就会自动把数据往abcd中塞,即function(data){...},
// data就是服务器返回的数据。
//3,最后创建script对象,并为其设置src=url,即可。
//4,最后的最后,不管是否跨域成功,都要删除已经创建的script对象,以及getJSONP中创建的方法,避免污染函数本身
//这是老师写代码的思路,下面两个是自己写的代码思路,最后一个比较适合自己。
//封装JSONP跨域函数
function getJSONP(url,callback){
//判断url是否为false,如果为false则直接返回,不执行
if (!url) {
return;
}
var arr=['a','b','c','d','e','f','g','j','h','i'];
//随机生成4个0到9之间的索引,对应数组arr的下边生成a到i之间的字母。组成一个函数名。
var r1=Math.floor(Math.random()*(9-0+1)+0);
var r2=Math.floor(Math.random()*(9-0+1)+0);
var r3=Math.floor(Math.random()*(9-0+1)+0);
var r4=Math.floor(Math.random()*(9-0+1)+0);
//这里的name,纯粹是一个属性,getJSON可自定义,与getJSON方法没有关系
var name='getJSONP'+arr[r1]+arr[r2]+arr[r3]+arr[r4];
//这里的name是作为getJSON方法对象的属性,用于存放服务器返回的数据
var cbname='getJSONP.'+name;
//判断url中地址是否含有"?"符号,jsonp作为url发送数据的变量,可以自定义
if (url.indexOf("?") === -1) {
url+="?jsonp="+cbname;
}else{
url+="&jsonp="+cbname;
}
//创建script标签
var script=document.createElement('script');
//定义被脚本执行的回调函数
getJSONP[name]=function(data){
try{
// && 如果条件全部为真,则返回最后一个
// && 如果有多为false,则返回第一个false的条件。
//如果callback为真,则执行callback(data)函数
callback && callback(data);
//捕获异常,并没有抛出
}catch(e){
///不执行
}finally{
//不管是否执行成功,都要进行删除操作如下:
//最后删除创建的函数getJSONP[name],以免污染getJSONP函数本身
delete getJSONP[name];
//删除script对象
script.parentNode.remove("script");
}
}
//给script设置src属性,因为src是可以跨域访问不同域名,协议,端口的数据
script.src=url;
//把script添加到DOM中的head末尾。
document.getElementsByTagName("head")[0].appendChild(script);
}
getJSONP('http://class.imooc.com/api/jsonp',function(data){
for (var i = 0; i < data.length; i++) {
console.log(data[i].picUrl+"---"+data[i].linkUrl);
}
});
/*//第一种自己的思路
/function getJSONP(url,callback){
//判断url是否有效
if (!url) {
return;
}
//如果url是否有传参数,并且给url传一个接受数据的函数jsonp=getJSONP.abcd
if (url.indexOf("?")===-1) {
//这里getJSONP.abcd为了偷懒,没有正式定义,正式应该使用随机生成,如下面例子。
url+="?jsonp=getJSONP.abcd";
}else{
//这里getJSONP.abcd为了偷懒,没有正式定义,正式应该使用随机生成,如下面例子。
url+="&jsonp=getJSONP.abcd";
}
//创建script对象
var script=document.createElement("script");
script.src=url;
//定义getJSONP.abcd函数,唯一的功能就是为了接收服务器返回的函数data
//即:function(data){...里面的代码块就是为了处理data}
getJSONP[abcd]=function(data){
try{
callback && callback(data);
}catch(e){
//
}finally{
delete getJSONP.abcd;
script.parentNode.remove("script");
}
}
}
getJSONP("http://class.imooc.com/api/jsonp",function(data){
console.log(data);
});*/
//第二种自己的思路
//跨域,获取不同域名,协议,端口的地址的数据,使用callback回调函数处理服务器返回的数据
/*function getJSONP(url,callback){
//判断url是否有效
if (!url) {
return
}
//以下是随机生成一个4位字母的name,其实也可以随便自定义个name,也可以执行
var arr=['a','b','c','d','e','f','g','h','i','j','k','l','m','n','h','o','p','q','r','s','z'];
var r1=Math.floor(Math.random()*arr.length),
r2=Math.floor(Math.random()*arr.length),
r3=Math.floor(Math.random()*arr.length),
r4=Math.floor(Math.random()*arr.length);
//这里的name可以随便自定 如:var name=abdcdsdf;
//这里只是为了正式点才使用了随机生成。
var name="getJSONP"+arr[r1]+arr[r2]+arr[r3]+arr[r4];
if (url.indexOf('?')===-1) {
//这里等jsonp也可以随便定义,只是形式上过渡而已,如:
//假如:url="https://www.baidu.com?a=3&jsonp=getJSONPP.getJSONPabcd"
//重点是为了给getJSONP对象添加一个getJSONPabcd函数用于接收服务器返回的data数据而已
url+="?jsonp=getJSONP."+name;
}else{
url+="&jsonp=getJSONP."+name;
}
//创建script对象,不管是否跨域成功都创建了script对象
var script=document.createElement("script");
//给script设置src属性
script.src=url;
//把script对象添加到head末尾
document.getElementsByTagName("head")[0].appendChild(script);
//定义getJSONP[name]函数,用于接收数据
getJSONP[name]=function(data){
//判断callback回调函数是否是有效的
//callback是用于处理服务器返回的数据
try{
callback&&callback(data);
}catch(e){
//有异常不处理
}finally{
//不管跨域是否成功
//都要删除已经创建的script对象,以及getJSONP.name的方法,避免污染getJSONP对象本身
delete getJSONP[name];
script.parentNode.remove(script);//一定要获得父元素后才可以进行删除指定对象
}
}
}
//随便给一个不同域名,不同协议,不同端口的地址进行测试
getJSONP('http://class.imooc.com/api/jsonp',function(data){
//不管获得什么数据记得先查看其类型,再进行操作
console.log(typeof data);
for (var i = 0; i < data.length; i++) {
//可以对该数据进行处理,如渲染到DOM树上
//把数据渲染到DOM树上有两种方式:
//1,使用document.createElement('a'); div.appendChild(创建的对象);
//2,str="<a href='"+data[i].linkUrl+"'><img src='"+data[i].picUrl+"'/></a>"
console.log(data[i]);
}
});*/
</script>
</body>
</html>