详细内容

1.认识JSONP跨域

1.1什么是跨域

跨域,是指浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对JavaScript实施的安全限制。无法跨域是浏览器对于用户安全的考虑,如果自己写个没有同源策略的浏览器,完全不用考虑跨域问题了。是浏览器的锅,对。

同源策略限制了一下行为:

Cookie、LocalStorage 和 IndexDB 无法读取

DOM 和 JS 对象无法获取

Ajax请求发送不出去

1.2什么是同源策略

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

浏览器执行javascript脚本时,会检查这个脚本属于哪个页面,如果不是同源页面,就不会被执行。

1.3跨域的解决办法

  1. 修改ajax同源协议(不建议,危险)
  2. 委托php文件中转跨域
  3. JSONP

2.JSONP办法解决跨域

注意:JSONP只支持GET请求,不支持POST请求

ajax请求受同源策略影响,不允许进行跨域请求,而script标签src属性中的链接却可以访问跨域的js脚本,利用这个特性,服务端不再返回JSON格式的数据,而是返回一段调用某个函数的js代码,在src中进行了调用,这样实现了跨域。

  • 简单举例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <-- 服务端 一个js文件 -->
    download("I am String!")

    <-- 客户端 -->
    <script>
    function download(data){
    alert("下载数据"+data);
    }
    </script>
    <script src="28.demo.js"></script>

上面的例子有2个问题:

  1. 在需要的时候加载数据
  2. 能否引入除.js文件以外的其他路径

第一个问题可以通过动态插入script标签解决

第二个问题,其实对于计算机来说,文件后缀是没有任何用处的。只决定优先用什么软件打开他。

所以JSONP跨域使用步骤为:

  1. 先去声明一个函数,这个函数有一个形参
  2. 在需要下载数据的时候,动态创建script标签,将标签src属性设置成下载数据的链接
  3. 当script插入到页面上时,就会调用封装好的函数将需要的数据传过来
  • 首先JSONP获得的数据需要支持JSONP操作 http://cdn.asilu.com/#weather
  • 下面通过一个天气查询的案例了解一下JSONP的实际操作

如果是一个支持JSONP参数的接口,我们可以在网址后面拼接上&callback=download,使得数据为JSONP格式,得到的字符串可以用https://www.bejson.com/可视化

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
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="bootstrap-3.3.7-dist/css/bootstrap.min.css">
<link rel="stylesheet" href="bootstrap-3.3.7-dist/css/buttons.css">
<script>
function download(data) {
var oT1=document.getElementById("t1");
var oInfo=document.getElementById("info");

oInfo.innerHTML=`城市:${data.city},PM2.5:${data.pm25}`;
//1.天气情况取出
var arr = data.weather;
var str=``;
for(var i=0;i<arr.length;i++){
str+=`<tr>
<td>${arr[i].date}</td>
<td>${arr[i].weather}</td>
<td>${arr[i].wind}</td>
<td>${arr[i].temp}</td>
</tr>`
}
oT1.innerHTML=str;
}
</script>
<script>
window.onload = function () {
var oSearch = document.getElementById("search");
var oCity = document.getElementById("city");
oSearch.onclick = function () {
if (!oCity.value) {
alert("请输入城市名字");
} else {
var oScript = document.createElement("script");
oScript.src = `https://api.asilu.com/weather/?city=${oCity.value}&callback=download`;
document.body.appendChild(oScript);
}
}
}
</script>
</head>

<body>
<div class="container">
<div class="panel panel-primary">
<div class="panel-heading">
<h2>天气查询</h2>
<span id="info"></span>
</div>
<div class="panel-body">
<div class="form-group">
<label for="city">城市名字:</label>
<input id="city" type="text" class="form-control">
</div>
<button id="search" class="button button-3d button-action button-pill form-control">查询该城市的天气</button>
</div>
<div class="panel-footer">
<table class="table table-bordered table-hover">
<thead>
<tr>
<th>日期</th>
<th>天气</th>
<th>风向</th>
<th>气温</th>
</tr>
</thead>
<tbody id="t1">

</tbody>
</table>
</div>
</div>
</div>
</body>

</html>

评论