天天看点

前端跨域解决办法之JSONP

由于JavaScript的同源策略限制,在当前JavaScript脚本中并不能操作来自非同一域下的资源,这就使得跨域问题之于前端工程师就像弹吉他之于民谣歌手——是非常重要的基本功。

跨域问题解决办法有很多种,比如W3C给出的CORS(Cross-Origin Resource Sharing,跨源资源共享),它的基本思想就是使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功还是失败;又比如以本域下的后端服务器做代理转发请求,从而获得资源来供给本域下的JavaScript使用;以上,都不是我想说的重点,重点是我想说一下JSONP。

JavaScript虽然受同源策略影响,但是script标签加载资源并不会被它限制。JSONP就是利用这一点进行跨域资源请求,在资源加载进来之前定义好一个函数,这个函数接收一个参数(数据),函数里面利用这个参数做一些事情然后需要的时候通过script标签加载对应远程文件资源,当远程的文件资源被加载进来的时候,就会去执行我们前面定义好的函数,并且把数据当作这个函数的参数传入进去。即,JSON with Padding,加载进来的资源一般是以json形式存在的,而这些资源被当做参数传递给回调函数。

撸代码:

<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>无标题文档</title>

<script>
function fn(data) {
	var oUl1 = document.getElementById('ul1');
	var html = '';

	for (var i=0; i<data.length; i++) {
		html += '<li>'+data[i]+'</li>';
	}
	oUl1.innerHTML = html;
}
window.onload = function() {
	
	var oBtn1 = document.getElementById('btn1');
	
	oBtn1.onclick = function() {
		
		var oScript = document.createElement('script');
		oScript.src = 'getData.php';
		document.body.appendChild(oScript);
	}
}
</script>
</head>

<body>
<span style="white-space:pre">	</span><input type="button" id="btn1" value="按钮" />
    <span style="white-space:pre">	</span><ul id="ul1"></ul>
</body>
</html>
           

以下是被调用的php文件:

<?php
$t = isset($_GET['t']) ? $_GET['t'] : 'num';
$callback = isset($_GET['callback']) ? $_GET['callback'] : 'fn';

$arr1 = array('111111','22222222','33333333','4444444','555555555555555555555');
$arr2 = array('aaaaaaaaaaaa','bbbbbbbb','cccccccccccc','ddddddddd','eeeeeeeeeeee');

if ($t == 'num') {
	$data = json_encode($arr1);
} else {
	$data = json_encode($arr2);
}

echo $callback.'('.$data.');';
           

可以看到,在php中以函数调用的形式输出,并将参数传入,这样即使php文件不在同一个域下,前端的JavaScript也能请求到,并且利用已经声明的函数进行调用。我们还可以将script的src属性改为有参数的形式:'getData.php?t=str',这样可以得到另外的资源。

同样的道理,我们还可以做一些更复杂丰富的应用。比如利用一些门户网站给出的api接口可以调用他们数据库里的资源,去完成我们想实现的各种功能,以后有机会再接着聊这个话题。

继续阅读