本文介绍如何通过动态创建和插入script标签的src属性,绕过浏览器同源策略实现跨域数据获取。通过解析服务端返回的JavaScript变量,可在页面中直接使用数据。进一步地,通过动态重建script节点并监听onload事件,模拟Ajax的按需请求与局部刷新功能,提供了一种无需后端CORS支持的轻量级跨域交互思路。
利用script标签src属性实现跨域数据获取与类Ajax交互
场景
假设存在两个不同域名的服务器,分别为a.com和b.com。在b.com上有一个接口b_return_js.php,用于返回特定数据。如果请求来自b.com自身的页面,可以直接使用Ajax技术请求该接口。然而,当请求来自a.com的页面时,由于浏览器的同源策略限制,直接请求会受阻,此时需要寻找其他解决方案。
b_return_js.php的接口代码:
代码如下:
$a = array(
array('username'=>'tony', 'age'=>25),
array('username'=>'yimeng', 'age'=>23),
array('username'=>'ermeng', 'age'=>22),
array('username'=>'sanmeng', 'age'=>21),
);
shuffle($a);
echo 'var userdata = '.json_encode($a).';'; //一般如果是b.com的站内请求就直接返回json_encode($a)了, 但如果要用src属性实现跨域, 这里我们需要将该值赋给一个js变量, 保证在script标签加载后的页面里能获取到这个数据并使用。
简单实现:静态加载跨域数据
简单实现
一种简单的做法是在a.com的页面中直接插入如下代码:
代码如下:
<script src="http://b.com/b_return_js.php"></script>
这样,a.com的页面在加载时即可获取到接口返回的数据。但这种方法存在明显缺陷:数据仅在页面初始加载时获取一次。如果希望像Ajax那样,在用户点击按钮等触发条件下动态获取最新数据并实现局部刷新,这种静态加载方式便不再适用。
类Ajax实现:动态加载与事件监听
类ajax实现
要实现类似Ajax的动态交互,核心思路是在触发条件(如点击事件)发生时,重新生成并插入上述script标签,从而再次从接口获取数据。尽管这一思路直观,但实际编码实现具有一定复杂度。
上代码:
假设a.com/scriptSrc.php页面中包含一个按钮:
<input type="button" id="ajax_request_from_b" value="来自B.com的请求"/> 每次点击都会从b.com/b_return_js.php接口获取数据, 类似ajax的实现代码:
代码如下:
function createScript()
{
//console.log(ele);
ele.src = 'http://b.com/b_return_js.php';
ele.type = 'text/javascript';
ele.language = 'javascript';
}
function getData()
{
console.log(userdata);
}
$('#ajax_request_from_b').click(function(){
//每次都需要重新加载这个script标签, 因此每次都要重新生成一个新的script标 签保证能从跨域服务器获取数据
if(ele && ele.parentNode)
{
//ele.parentNode.removeChild(ele); //这种删除不能将ele彻底从内存删除,只是移除了在dom中的位置
for (var property in ele) {
delete ele[property]; //彻底删除
}
}
ele = document.createElement('script'); //这是一个新的ele
createScript();
document.getElementsByTagName("head")[0].appendChild(ele);
ele.onload = function(){getData()}; //script元素加载后方可获取userdata, 每次获取的都是随机顺序的用户信息
});
通过上述方式,每次点击按钮都会重新向接口请求数据,效果上类似于Ajax请求。这虽然是一种基于JavaScript的跨域实现方案,且代码略显繁琐,但提供了一种可行的技术思路。