详解Javascript几种跨域方式总结

在客户端编程语言中如javascript,同源策略规定跨域之间的脚本是隔离的,一个域的脚本不能访问和操作另外一个域的绝大部分属性和方法。只有当两个域具有相同的协议,相同的主机,相同的端口时,我们就认定他们是相同的域。可是在实际开发中我们经常需要获取其他域的资源,这个时候各种不同的跨域资源方式就各显神通了,今天主要来总结一下工作中常用的几种跨域方式,以备查询。

1.window.name

window 对象的name属性是一个很特别的属性,当在 frame 中加载新页面时,name 的属性值依旧保持不变。那么我们可以在页面 A中用iframe加载其他域的页面B,而页面B中用JavaScript把需要传递的数据赋值给window.name,iframe加载完成之后,此时 name 属性值可被获取到,以访问 Web 服务发送的信息。但 name 属性仅对相同域名的 frame 可访问。这意味着为了访问 name 属性,当远程 Web 服务页面被加载后,必须导航 frame 回到原始域。即页面A修改iframe的地址,将其变成同域的一个地址,然后就可以读出window.name的值了。一旦 name 属性获得,销毁 frame 。这个方式非常适合单向的数据请求,而且协议简单、安全。

页面B()代码如下:

<script type="text/javascript"> window.name = 'I was there!'; // 这里是要传输的数据,大小一般为2M,IE和firefox下可以大至32M左右 // 数据格式可以自定义,如json、字符串 </script>

页面A()代码如下:

<script type="text/javascript"> var state = 0, iframe = document.createElement('iframe'), loadfn = function() { if (state === 1) { var data = iframe.contentWindow.name; // 读取数据 console.log(data); //弹出'I wasthere!' (function(){ //获取数据以后销毁这个iframe。 iframe.contentWindow.document.write(''); iframe.contentWindow.close(); document.body.removeChild(iframe); })(); } else if (state === 0) { state = 1; // 设置的代理页面使其回原始域 iframe.contentWindow.location = "http://www.jack.com/proxy.html"; } }; iframe.src = 'http://www.jesse.com/data.html'; if (iframe.attachEvent) { iframe.attachEvent('onload', loadfn); } else { iframe.onload = loadfn; } document.body.appendChild(iframe); </script>

2.具备src的标签

虽然浏览器默认禁止了跨域访问,但并不禁止在页面中用标签的src属性引用其他域的文件。根据这一点,可以方便地通过创建具有src属性的节点方法来实现完全跨域的通信。使用这种原理的跨域方式有以下几种:

动态创建script

例如我要从域A的页面pageA加载域B的数据,那么在域B的页面pageB中我以JavaScript的形式声明pageA需要的数据,然后在 pageA中用script标签把pageB加载进来,那么pageB中的脚本就会得以执行。

pageA()代码如下:

function getData(data){ //这里是对获取的数据的相关操作 console.log(data); //数据获取到后移除创建的script标签 document.body.removeChild(originData); } var originData = document.createElement('script'); originData.src = 'http://www.jesse.com/data.js'; originData.setAttribute("type", "text/javascript"); document.body.appendChild(originData);

pageB()代码如下:

getData('这里是远程跨域获取的数据');//数据格式可以自定义,如json、字符串

jsonp

在用$.ajax()获取远程数据时,如果是跨域资源则可以使用jsonp方法,以前一直以为jsonp是ajax的一种,后来才明白他们根本就不是一回事。ajax是以xhr方式请求数据的,而jsonp是以script方式请求数据的,这个就是和上面的动态创建script方式一样。

pageA()代码如下:

$.ajax({ //JSONP不支持POST方式 type:"GET", url:"http://www.jesse.com/data.php", dataType:"jsonp", //自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名,也可以写"?",jQuery会自动为你处理数据 jsonpCallback:"getData", success: function(data){ console.log(data); }, error: function(){ console.log('fail'); } })

pageB()代码如下:

<?php $callback = $_GET['callback'];//得到回调函数名,这里是getData $data = array('a','b','c');//要返回的数据 echo $callback.'('.json_encode($data).')';//输出 ?>

3.document.domain

对于主域相同而子域不同的例子,可以通过设置document.domain的办法来解决。 具体的做法是可以在和两个文件中分别加上 document.domain = "a.com";然后通过a.html文件中创建一个iframe,去控制iframe的contentDocument,这样两个js文件之间就可以 “交互”了。当然这种办法只能解决主域相同而二级域名不同的情况

上的a.html

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wwzjjg.html