JSONP解决跨域

489 阅读2分钟

在项目开发中,前端请求后端接口常常会遇到跨域问题,我们前端通常的做法是通过反向代理或者JSONP来解决。JSONP中,我们要把接口和字段(字段通常包括 json数据 和 回调的方法...)写在 script 标签的 src 的属性值中,由于script 的 src 属性不受同源策略的限制,所以当 src 的属性值是我们要请求的接口和字段时,自然也就可以跨域访问。

JSONP其实就是使用回调函数的原理,结合不受同源约束的 src 属性来实现跨域请求的。

  • 通过动态创建script标签,给 src 传递不同参数,获取后端返回的不同的数据,这个数据形如 getInfo({'name':'edward'}), 然后将这个script标签插入到当前代码中。
  • 当我们成功获取到后台返回来的数据时,相当于调用了一次前端事先创建好的回调函数,这就是JSONP的大体流程。

话不多说,直接上代码

例如,我们现在在服务端中有两组数组,一组存储的是歌名,一组存储的是电影名,点击不同的按钮显示不同的数据。

首先我们先来完成html的代码:

<button id="btn1">音乐排行</button>
<ul id="list1">
    
</ul>
<button id="btn2">电影排行</button>
<ul id="list2">
    
</ul>

我们的需求是点击两个按钮分别显示不同的数据,下面是服务端的代码:

<?php 
header("Content-type:text/html;Charset=utf-8");
​
// 接收数据 
$parm = $_GET['parm'] ? $_GET['parm'] : 'music';
$callback = $_GET['callback'];
​
// 模拟数据库存储的数组 
$arr_music = ['残酷月光','孤身','Come back','情深深雨蒙蒙','救赎'];
$arr_movie = ['肖申克的救赎','流浪地球','盗梦空间','我不是药神','阿甘正传'];
​
// 判断传输的数据是什么
if($parm === "music") {
    $data = $arr_music;
}else {
    $data = $arr_movie;
}
​
// 传输数据 
echo $callback . "(" . json_encode($data) . ")"; // 将数据传输之前转换成json

JS代码:

// 点击按钮请求数据  
let oBtn1 = document.getElementById('btn1');
let oBtn2 = document.getElementById('btn2');
​
// 创建回调函数 当接收到服务端返回的回调函数时执行
function getdata1(data) {
    // 获取元素赋值 
    let list1 = document.getElementById('list1');
    html = '';
    for(let i=0;i<data.length;i++){
        html += "<li>" + data[i] + "</li>";
    }
    list1.innerHTML = html;
​
}
function getdata2(data) {
    // 获取元素赋值 
    let list2 = document.getElementById('list2');
    html = '';
    for(let i=0;i<data.length;i++){
        html += "<li>" + data[i] + "</li>";
    }
    list2.innerHTML = html;
​
}
​
oBtn1.onclick = ()=> {
    // 创建script标签 ,动态插入 
    let script = document.createElement('script'); 
    let url = "02.jsonp.php?parm=music&callback=getdata1";//请求url带上参数和回调函数
    script.src = url;
    document.getElementsByTagName('body')[0].appendChild(script);
};
​
oBtn2.onclick = ()=> {
    // 创建script标签 ,动态插入 
    let script = document.createElement('script'); 
    let url = "02.jsonp.php?parm=movie&callback=getdata2";//请求url带上参数和回调函数
    script.src = url;
    document.getElementsByTagName('body')[0].appendChild(script);
};

这样,我们就通过JSONP的形式读取到了后台文件的数据。这就是jsonp实现跨域的原理和大致流程

注意

jsonp跨域请求的关键就在于服务端要在返回的数据外层包裹一个客户端已经定义好的函数

JSONP因为通过src属性,所以只能通过get传输数据。