关于JSONP跨域

JSONP是干嘛的

提到JSONP,首先想到的就是AJAX,因为人们时常将它们放在一起说。那么,它们到底是什么关系呢?

其实它们本身并没有实质的关系,只是JSONP可以解决AJAX一件办不到的事情。哪件事情是AJAX办不到的?就是跨域!

简单来说,JSONP就是一种跨域的手段。

跨域:意思是说,在当前网址去获取另一个域下的数据。浏览器有一个“同源策略”——两个页面的域名必须在同域的情况下,才能允许通信。

所谓同源是指,域名,协议,端口相同。

浏览器的“同源策略”有效地阻止了很多危险行为,因为在没有“同源策略”的情况下,网站的信息可以被所有人任意获取,那么用户的隐私就受不到保护了,这是很可怕的。但事情有利有弊,“同源策略”也带来了麻烦,这时如果我们想从信任的网站获取数据,显然也做不到了。

JSONP怎么用

可能JSONP听起来很高大上,但其实其原理很简单,是我们每天都接触的。”同源策略”虽然很厉害,阻止了一个页面到另一个页面的通信,可是src指向的路径它放过了。提到src,我们再熟悉不过了,<img><script><iframe>都有src属性。JSONP就是利用<script>标签来实现跨域通信的。

讲一个简单的小例子:

现在假设有两个域,需要互相通信,分别是:www.aaa.comwww.bbb.com

www.aaa.com中:

1
2
3
4
5
6
7
8
<script src='http://www.bbb.com/abc.js'></script>
<script>

function abc(data){
alert(data['name']);
}

</script>

www.bbb.com/abc.js中:

1
abc({'name':'wungjyan','age':23});

结果页面弹出了wungjyan

JSONP工作过程:通过<script>标签,获取到www.bbb.com/abc.js,里面有一个函数abc,函数会被加载到www.aaa.com。加载完成后,就执行abc函数,而在www.aaa.com中已经定义好了一个abc函数,函数里写了一些处理数据的语句。这样就简单地实现了跨域访问数据了,这也就是JSONP的原理了。

JSONP实例

运用JSONP做一个类似百度搜索下拉框。

在这之前,先取到百度的接口。

打开百度首页,在输入框随便输入点什么,比如,输入a,

打开Network,点击all,找到地址

这个地址是:https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=a&json=1&p=3&sid=23534_1436_21084&req=2&csor=1&cb=jQuery110206731850454839907_1506167060552&_=1506167060555

只取本次实例需要的参数,精简为:https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=a&cb=jQuery110206731850454839907_1506167060552&_=1506167060555

其中wd是关键字,即输入的内容,cb是回调函数,百度内定的,cb后面的是函数名,可以修改,相当于上面小例子中的abc函数。

现在就修改为abc,并输入到浏览器地址栏中,看看得到什么内容:

可以看到,这个abc函数里的参数是一个json数据,其中s就是我们需要的数据。

完整代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>百度下拉菜单</title>
<style type="text/css">
#text{
width: 300px;
height: 30px;
border:1px solid #6495ED;
line-height: 30px;
font-size: 16px;
}

#ul1{
margin: 0;
padding:0;
border:1px solid #6495ED;
border-top: none;
width: 300px;
display: none;
}
#ul1 li{
list-style: none;
margin-top: 5px;
}

#ul1 li a{
font-size: 16px;
color: #696969;
text-decoration: none;
}
</style>
</head>
<body>
<input type="text" id="text">
<ul id="ul1">

</ul>

<script>
//定义abc函数,添加数据处理程序
function abc(data){
var oUl=document.getElementById('ul1');
var html='';
if (data.s.length) {
oUl.style.display='block';
for(var i=0;i<data.s.length;i++){
html+="<li><a target='_blank' href='https://www.baidu.com/s?wd="+data.s[i]+"'>"+data.s[i]+"</a></li>";
}
oUl.innerHTML=html;
}else{
oUl.style.display='none';
}
}


var oT=document.getElementById('text');
var oBtn=document.getElementById('btn');
var oUl=document.getElementById('ul1');

oT.onkeyup=function(){
if (oT.value!='') {
var aScript=document.createElement('script');
aScript.src='https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd='+oT.value+'&cb=abc';
document.body.appendChild(aScript);

if(aScript){ //避免过多script标签
document.body.removeChild(aScript);
}

}else{
oUl.style.display='none';
}
}



</script>
</body>
</html>

代码中,动态添加<script>标签,加载完成后就执行abc函数,使获取到的数据展示在页面中。