JSONP的使用
使用<script>标签从远程获取js文件的思路,可以变通为从其他服务器获取JSON文件。不过这样需要对服务器的json文件做修改。(受同源策略的影响,浏览器从其他服务器无法取得其他服务器的json数据)。
从服务器返回JSONP
back-jsonp.php文件:
<?php
header("content:application/json;chartset=uft-8");
$callback = isset($_GET['getjsonp']) ? $_GET['getjsonp'] : die('必须提供查询字段名称');
// 包裹json字符串的函数名
$funcName = 'jsonp_callback';
//
if ($callback !== $funcName) {
exit('函数名称不正确');
}
$res = [
'code' => 0,
'msg' => '返回成功',
'data' => array(
'title' => '这是一个标题',
'desc' => '这是描述',
'list' => array(
'这是新闻1',
'这是新闻2',
'这是新闻3'
)
)
];
$json = json_encode($res, JSON_UNESCAPED_UNICODE);
// jsonp_callback({$json});
$jsonp = "{$funcName}({$json})";
echo $jsonp;
// 在当前目录下生成一个静态的js文件,用于html文件请求的
$filepath = str_replace('\\', '/', __DIR__);
$filename = $filepath . '/' . 'back-jsonp.js';
$file = file_put_contents($filename, $jsonp);
if (!$file) {
exit('生成js文件失败');
}
JSONP的格式是吧标准的JSON文件包装在一对圆括号中,圆括号又前置一个任意字符串。这个字符串即所谓的P(填充,padding)。由于有一对圆括号,因此返回的数据在客户端可能会有一次函数调用,或者为某个变量赋值。在php实现jsonp非常简单:
echo 'callback_funcName(' . $json . ')';
在前端获取JSONP的方法上,我推荐一个插件:jsonp,点击跳转到github地址。生成后的格式,请见(五)
使用JSONP函数
<script src="jsonp.js"></script>
<script>
// 请求的地址是:back-jsonp.php?getjsonp=getjsonp_callback
jsonp(
'back-jsonp.php', // url
// opts
{
// 请求的查询字段名称
param: 'getjsonp',
// 包裹json数据的函数名,必须要前后端一致起来
// 后台也可以使用$_GET动态的名称,这个根据需要
name: 'jsonp_callback'
},
// 注意 返回的是两个值 第一个代表失败,第二个代表成功后的数据
function(err, data) {
console.log('使用jsonp函数', data);
}
);
</script>
其中name属性比较重要,必须要跟后台包裹json字符串的函数名统一起来,否则会报错,进入失败的获取状态。而param如果后台不做限制,要求并不高,设置可以忽略此参数,让后台的$_GET['..']去自动赋予。
使用JQ
<!-- 下面使用JQ -->
<script src="http://vip.qdxin.cn/navmenu/js/jxinq111.js"></script>
<script>
// 请求的地址是:back-jsonp.php?getjsonp=jsonp_callback
// 缺点是无法捕获失败的回调
$.ajax({
type: 'GET',
url: 'back-jsonp.php',
dataType: 'jsonp',
// 请求的查询字段名称,如果后台做了限制,那么就必须一致,否则不做要求
jsonp: 'getjsonp',
// 包裹json数据的函数名, 默认是jq自动生成的随机名,必须前后端一致才能获取到数据
jsonpCallback: 'jsonp_callback'
})
.done(function(data) {
console.log('使用JQ的函数', data);
})
.fail(function(err) {
console.log('使用JQ的函数,出错了', err);
});
</script>
Vue中使用JSONP函数
vue-cli中进行安装 $ npm install jsonp
// 对Jsonp函数的一次封装
import jsonp from 'jsonp';
function getJsonP(url) {
return new Promise((resolve, reject) => {
jsonp(
url,
{
name: 'ztcallback'
},
(err, data) => {
if (!err) {
resolve(data);
} else {
reject(err);
}
}
)
});
}
export default getJsonP;
// 如何使用 : 使用jsonp请求数据解决跨域问题
import getJsonP from "common/js/getJsonP";
return getJsonP(url).then(res => {
return Promise.resolve(res);
}).catch(err => {
return Promise.reject(err);
})
从静态JS文件中中获取JSONP
后台有些需求比较奇葩的,比如获取数据原本从库中获取,但是非要求将json生成静态的json文件进行获取等等。因此就有了将JSONP字符串生成静态的js文件这种需求。具体生成的方法请参考一、从服务器返回jsonp。生成的JS文件如下(back-jsonp.js):
jsonp_callback({
"code":0,
"msg":"返回成功",
"data": {
"title":"这是一个标题",
"desc":"这是描述",
"list": ["这是新闻1","这是新闻2","这是新闻3"]
}
});
使用JQ获取静态JS
// 请求的地址是:back-jsonp.js?whatever=jsonp_callback
// 缺点是无法捕获失败的回调
$.ajax({
type: 'GET',
url: 'back-jsonp.js',
dataType: 'jsonp',
// 请求的查询字段名称,如果后台做了限制,那么就必须一致,否则不做要求
jsonp: 'whatever',
// 包裹json数据的函数名, 默认是jq自动生成的随机名,必须前后端一致才能获取到数据,否则会执行错误的数据
jsonpCallback: 'jsonp_callback'
})
.done(function(data) {
console.log('使用JQ的函数', data);
})
.fail(function(err) {
console.log('使用JQ的函数,出错了', err);
});
使用JSONP函数获取静态js
// 请求的地址是:back-jsonp.js?whatever=jsonp_callback
jsonp(
'back-jsonp.js', // url
// opts
{
// 请求的查询字段名称
param: 'whatever',
// 包裹json数据的函数名, 当需要从静态的js文件中获取jsonp数据时候
// 这个字段的名称必须与静态文件中的一致
name: 'jsonp_callback'
},
// 注意 返回的是两个值 第一个代表失败,第二个代表成功后的数据
function(err, data) {
console.log('使用jsonp函数', data);
}
);
当从静态js文件中获取jsonp的时候,只要关注静态文件中的函数名与jsonp函数: name, JQ的jsonpCallback一致即可。而查询字段就不那么重要了,是什么都行。
最后补充一句:附件的案例,请在服务器环境下运行。