众所周知,为了安全性考虑浏览器是不支持跨域请求的,哪些请求是跨域请求?
什么是跨域请求
总之,同源是指 协议、域名、端口都相同,否则都算跨域。
本文用JSONP的方式实现了一个小小的跨域请求demo,在<script>标签中请求另外一台服务器的脚本,回调函数拿到数据后渲染echart,蛮有意思。
效果如图:
test559是我的开发机
//board.html
获取到url传参date后,拼接为src链接地址,动态生成一个script标签
<script src="https://test329.suanshubang.com/Stats.php?callback=callback&date=20200715"></script>
,
跨域请求到test329上;
向php脚本传递了两个参数,一个是callback回调函数,用于取回数据;另一个是date参数,是传递给脚本的入参。
<!DOCTYPE html>
<html>
<head>
<title>已分配任务的流转情况</title>
<meta charset="utf-8">
<script src="https://cdn.staticfile.org/echarts/4.7.0/echarts.min.js"></script>
<div id="main" style="width: 900px;height:400px;"></div>
<script>
var g_data=[]
function callback(data){
console.log(data);
g_data=data;
var myChart = echarts.init(document.getElementById('main'));
// 指定图表的配置项和数据
option = {
tooltip: {
trigger: 'axis',
axisPointer: { // 坐标轴指示器,坐标轴触发有效
type: 'shadow' // 默认为直线,可选为:'line' | 'shadow'
}
},
legend: {
data: g_data.legend
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: [
{
type: 'category',
data: g_data.xAxis
}
],
yAxis: [
{
type: 'value'
}
],
series: g_data.series
};
// 使用刚指定的配置项和数据显示图表。
myChart.setOption(option);
}
</script>
<script language="javascript">
function GetRequest() {
var url = location.search; //获取url中"?"符后的字串
var theRequest = new Object();
if (url.indexOf("?") != -1) {
var str = url.substr(1);
strs = str.split("&");
for(var i = 0; i < strs.length; i ++) {
theRequest[strs[i].split("=")[0]]=unescape(strs[i].split("=")[1]);
}
}
return theRequest;
}
var req = GetRequest();
var req1 = JSON.stringify(req.date);
const script = document.createElement('script');
script.src = "https://test329.suanshubang.com/Stats.php?callback=callback&date=" + req1;
script.async = false;
document.head.appendChild(script);
</script>
</head>
</html>
//Stats.php
$date = $_GET['date'];
获取入参date;
$params = $_GET['callback'];
获取回调函数;
echo $params . '(' . json_encode($output) . ')';
调用回调函数,即可将后端数据outout传递给前端。
<?php
$date = $_GET['date'];
$date = substr($date, 1, 8);
Bd_Init::init('assistantcheck');
$stats = new Stats();
$output = $stats->execute(['date' => $date]);
$params = $_GET['callback'];
echo $params . '(' . json_encode($output) . ')';
class Stats
{
private $objCheckTaskMain = null;
public function __construct()
{
$this->objCheckTaskMain = new Service_Data_Task_CheckTaskMain();
}
public function execute($input)
{
$targetDate = isset($input['date']) && intval($input['date']) != 0 ? intval($input['date']) : date('Ymd', time());
$zeroTime = strtotime($targetDate);
$sql = "select item,check_status,count(*) as cnt from tblCheckTaskMain where delete_time =0 and dispatch_time >= " . $zeroTime . " group by item,check_status";
$ret = $this->objCheckTaskMain->query($sql);
$item_status_cnt = [];
foreach ($ret as $agg_data) {
$key = $agg_data['item'] . '-' . $agg_data['check_status'];
$item_status_cnt[$key] = $agg_data['cnt'];
}
$check_status_set = array_unique(array_column($ret, 'check_status'));
sort($check_status_set);
$legend = [];
foreach ($check_status_set as $check_status) {
$legend[$check_status] = Conf_Config::CHECK_STATUS_MAP[$check_status];
}
$xAxis = [3 => '订正', 4 => '上镜', 5 => '微信单聊', 6 => '微信群聊', 7 => '兼职辅审', 8 => '兼职纯批'];
$series = [];
foreach ($legend as $check_status => $check_status_name) {
$tmp = [
'name' => $check_status_name,
'type' => 'bar',
'data' => $this->getSeriesData($check_status, $xAxis, $item_status_cnt),
];
$series[] = $tmp;
}
return [
'legend' => array_values($legend),
'xAxis' => array_values($xAxis),
'series' => array_values($series),
];
}
private function getSeriesData($check_status, $xAxis, $item_status_cnt)
{
$data = [];
foreach ($xAxis as $item => $item_name) {
$key = $item . '-' . $check_status;
$data[] = isset($item_status_cnt[$key]) ? intval($item_status_cnt[$key]) : 0;
}
return $data;
}
}
过程中遇到的坑:
document.createElement('script');
是动态生成一个script标签,追加到html中,这个script会最后执行。导致echart拿不到后端数据,渲染失败。
后来,将渲染echart的代码放到callback里函数执行,迎刃而解(前端小白两股瑟瑟)。
鸣谢: https://blog.csdn.net/weixin_43837229/article/details/90720536
网友评论