参考资料:http://www.cnblogs.com/dowinning/archive/2012/04/19/json-jsonp-jquery.html
JSON 是一种数据格式。JSONP(JSON with padding)顾名思义是传递 JSON 数据的方法。jsonp 用来解决跨域问题。
是否跨域要看:
- 是否同协议(http 和 https)
- 是否同域名(子域不同也算,比如 www 和其他子域)
- 是否同端口(端口不同也是跨域)
常见的解决跨域的办法:
- 使用 iFrame 方位另一个域,然后再读取 iframe 的内容,jQuery 有封装
- jsonp,需要服务器支持。
- 设置 http 头,Access-Control-Allow-Origin:*。据说 IE 的一些版本不识别这个 http 头。
- 服务器代理,比如 vue-cli 开发环境下中可以配置 proxyTable。也可以用 nginx 来配置。
产生 jsonp 这种方法的原因:
- ajax 请求数据的时候不能跨域访问(可以通过代理来解决)
- 但是 html 中凡是拥有 src 这种属性的标签,
src
都有跨域的能力,比如script
,img
,iframe
(vue-cli 等前端工程化,所谓的开发环境解决 axios 跨域是因为工程化前端开的端口和后端不一样,所以这里存在跨域,用proxyTable
代理来解决跨域,编译打包后部署到服务器上,一般来讲 axios 又不存在跨域了,都在一个端口上,所以生产环境不用解决。一次项目的那个 bug,图片的路径不对,在开发环境下,localhost:8061 要访问 localhost:8080 上的资源,用proxyTable
代理解决,但是部署到生产环境下后还是存在跨域的问题,proxyTable 不起作用,因此图片资源访问不到,设置合理的webpack.DefinePlugin
来拼接正确的图片路径就可以访问到了)
JSONP 的简单实现:
local.com/a.html:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script type="text/javascript">
function test(data){
console.log('获取的数据是:' + data.result)
}
</script>
<script type="text/javascript" src="http://remote.com/remote.js"></script>
</head>
<body>
</body>
</html>
remote.com/remote.js:
test({"result":"hello"})
这样跨域获取数据就算成功了。
再进一步,在加载的 url 中加入一些参数,参数让服务器知道该调用的函数名:
local.com/a.html:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script type="text/javascript">
function test(data){
console.log('获取的数据是:' + data.result)
}
var url = "http://remote.com/jsonp/check?code=name&callback=test";
var script = document.createElement('script');
script.setAttribute('src', url);
// 加载当前 head 节点下的最后一个
document.getElementsByTagName('head')[0].appendChild(script);
</script>
</head>
<body>
</body>
</html>
服务端生成这样内容的 js 文件返回:
test({"name":"Annie"})
jQuery 中这些都帮我们做好了。