打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
JavaScript跨域详解(2) | Rolf Zhang 博客

JavaScript跨域详解(2)

发表于

3.4、iframe+location.hash

这种方法比上面两种稍微繁琐一点,原理如下:

www.a.com下的a.html想和www.b.com下的b.html通信(在a.html中动态创建一个b.html的iframe来发送请求);

但是由于“同源策略”的限制他们无法进行交流(b.html无法返回数据),于是就找个中间人:www.a.com下的c.html(注意是www.a.com下的);

b.html将数据传给c.html(b.html中创建c.html的iframe),由于c.html和a.html同源,于是可通过c.html将返回的数据传回给a.html,从而达到跨域的效果。

三个页面之间传递参数用的是location.hash(也就是www.a.html#sayHello后面的’#sayHello’),改变hash并不会导致页面刷新(这点很重要)。

具体代码如下:

www.a.com/a.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//通过动态创建iframe的hash发送请求
function sendRequest(){
  var ifr = document.createElement('iframe');
  ifr.style.display = 'none';
  //跨域发送请求给b.html, 参数是sayHello
  ifr.src = 'http://www.b.com/b.html#sayHello';
  document.body.appendChild(ifr);
}
//获取返回值的方法
function checkHash() {
  var data = location.hash ?
     location.hash.substring(1) : '';
  if (data) {
    //处理返回值
    alert(data);
    location.hash='';
  }
}
//定时检查自己的hash值
setInterval(checkHash, 2000);
window.onload = sendRequest;

 

www.b.com/b.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function checkHash(){
  var data = '';
  //模拟一个简单的参数处理操作
  switch(location.hash){
    case '#sayHello': data = 'HelloWorld';break;
    case '#sayHi': data = 'HiWorld';break;
    default: break;
  }
  data && callBack('#'+data);
}
function callBack(hash){
  // ie、chrome的安全机制无法修改parent.location.hash,
  // 所以要利用一个中间的www.a.com域下的代理iframe
  var proxy = document.createElement('iframe');
  proxy.style.display = 'none';
  // 注意该文件在"www.a.com"域下
  proxy.src = 'http://www.a.com/c.html'+hash;
  document.body.appendChild(proxy);
}
window.onload = checkHash;

 

www.a.com/c.html

1
2
3
4
5
//因为c.html和a.html属于同一个域,
//所以可以改变其location.hash的值
//可通过parent.parent获取a.html的window对象
parent.parent.location.hash =
    self.location.hash.substring(1);

可能有人会有疑问,既然c.html已经获取了a.html的window对象了,为何不直接修改它的dom或者传递参数给某个变量呢?

原因是在c.html中修改 a.html的dom或者变量会导致页面的刷新,a.html会重新访问一次b.html,b.html又会访问c.html,造成死循环……囧呀~

所以只能通过location.hash了。这样做也有些不好的地方,诸如数据容量是有限的(受url长度的限制),而且数据暴露在url中(用户可以随意修改)……

 

3.5、postMessage(html5)

html5中有个很酷的功能,就是跨文档消息传输Cross Document Messaging)。新一代浏览器都将支持这个功能:Chrome 2.0+、Internet Explorer 8.0+, Firefox 3.0+, Opera 9.6+, 和 Safari 4.0+ 。

使用方法如下:

1
otherWindow.postMessage(message, targetOrigin);

说明:

  • otherWindow: 对接收信息页面的window的引用。可以是页面中iframe的contentWindow属性,window.open的返回值等。
  • message: 所要发送的数据,string类型。
  • targetOrigin: 用于限制otherWindow,“*”表示不作限制。

www.a.com/a.html中的代码:

html:

1
<iframe id="ifr" src="http://www.b.com/b.html"></iframe>

script:

1
2
3
4
5
6
window.onload = function() {
    var ifr = document.getElementById('ifr');
    // 若写成'http://www.c.com'就不会执行postMessage了
    var targetOrigin = 'http://www.b.com';
    ifr.contentWindow.postMessage('sayHello', targetOrigin);
};

www.b.com/b.html的script

1
2
3
4
5
6
7
8
//通过message事件来通信,实在太爽了
window.addEventListener('message', function(e){
  // 通过origin属性判断消息来源地址
  if (e.origin == 'http://www.a.com' &&
    e.data=='sayHello') {
    alert('Hello World');
  }
}, false);

 

3.6、使用flash

由于本人对flash不怎么熟悉,此处暂时忽略之~

 

3.7、Cross Frame

行文至此,突然在口碑网UED博客上看到了一篇 《跨域资源共享的10种方式》,对跨域的多种方法都有介绍(虽然有源码,但多数都是直接调用YUI库的,比较难看出原理)。

里面提到了Cross Frame这种方法,似乎挺不错的,改日一定翻源码来研究。

 

4、总结

研究了几天,虽然对多种跨域方法都有所了解了,但是真要投入应用还是明显不够的(还是需要借助一些js库)。

每种方法都有其优缺点,使用的时候其实应该将多种跨域方法进一步封装一下,统一调用的接口,利用js来自动判断哪种方法更为适用 。

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
window.parent. - 依城的日志 - 网易博客
window.parent 判断是否是被嵌入iframe里面
深入理解前端跨域方法和原理
js实现iframe跨页面调用函数的方法
重新加载父窗口里的iframe页面的几种方法
iframe子页面调用父页面javascript函数的方法
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服