最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
js利用iframe实现跨域通信例子
时间:2016-03-18 编辑:简简单单 来源:一聚教程网
127.0.0.1 www.myapp.com
127.0.0.1 sample.myapp.com
127.0.0.1 www.otherapp.com
document.domain
、URL.hash
、 Cross-fragment
、 Window.name
、 postMessage
。document.domain
属性,就很容易使其相互通信。在 HTML 规范中 document.domain
是一个只读属性,现代浏览器允许将其设置为父域名(不是顶级域名)。例如,一个是 www.myapp.com
的页面,可以设置为 myapp.com
,而另一个来自 sample.myapp.com
的页面也可以设置为myapp.com
,下图展示了 document.domain
的工作原理:document.domain
属性设置为相同的父域名,来实现不同子域名之间的跨域通信,这并不属于同源策略限制的范畴。但是,严格来说,子域名跨域的解决方案最适用于内部应用之间的跨域通信。这里给出的例子和前文提到的稍有区别,上代码,主页面如下:
iframe页面如下:
父页面和iframe中都设置document.domain
为myapp.com
,父页面中按钮被点击后就去调用iframe中的sayHello
方法,子页面同时也会调用父页面的sayHello
方法。效果如下:
hash
的变化,hash
的任何改变都不会导致页面刷新。hash
已经被广泛使用在支持局部刷新的 SPA 应用中,用来记录用户的访问路径。在跨域解决方案中,hash
也非常有用,来自不同源的页面可以相互设置对方的 URL,包括 hash
值,但仍被限制获取对方的hash
值。文档之间可以通过 hash
来相互通信。如下图所示的例子:
iframe代码如下:
主页面向iframe传递参数通过改变iframe的hash值,iframe不断获取自己的hash值,一旦发生变化就立即显示主页面传来的消息,并且通过设置主页面的hash就可以像主页面传递消息了,这样实际就可以完成双向的跨域通行了。效果如下:
hash
已经被用于其他用途,对于这样的网站用 hash
跨域将非常复杂(需要从 hash
中合并和分离出消息)。因此我们就有了基于 hash
的一个升级版:cross-fragment
,其原理如下图所示:这种方案和前一种实质是相同的,都是通过 url 的 hash
来传递参数,但是需要配合一个同域的代理页面来完成跨域。先看主页面代码:
请求代理页面:
// http://www.otherapp.com:3000/demo3-req-proxy
var hash = window.location.hash;
if(hash && hash.length>1){
var request = hash.substring(1, hash.length);
var obj = JSON.parse(decodeURI(request));
var data = obj.data;
// 处理数据
parent.frames[obj.frameName].getData(data); //目标页面的getData方法
}
目标页面:
响应代理页面:
// http://www.myapp.com:3000/demo3-res-proxy
var hash = window.location.hash;
if(hash && hash.length>1){
var request = hash.substring(1, hash.length);
var obj = JSON.parse(decodeURI(request));
var data = obj.data;
// 处理数据
parent.parent.getResponse(data); //主页面的getResponse方法
}
这个例子中先在主页面(来自myapp)放置一个otherapp下的iframe(目标页面),点击按钮后就在主页面中构造一个隐藏的iframe(和目标页面同域,来自otherapp,请求代理页面),通过这个请求代理页面调用目标页面的getData方法,这个方法接收传来的数据,处理完成后,构造一个隐藏的iframe(和主页面同域,来自myapp,响应代理页面),通过响应代理页面调用主页面中的getResponse方法。效果如下
window.name
跨域是一个巧妙的解决方案,一般情况下,我们使用 window.name
的情况如下:- 使用
window.frames[windowName]
得到一个子窗口 - 将其设置为链接元素的
target
属性
window.name
的值始终保持不变。由于 window.name
这个显著的特点,使其适用于在不同源之间进行跨域通信,但这是个不常用的属性。那么怎么在同源策略下使用呢?下图显示了如何使用 window.name
来跨域通信。当页面 A 想要从另一个源获取资源或 Web 服务,首先在自己的页面上创建一个隐藏的 iframe
B,将 B 指向外部资源或服务,B 加载完成之后,将把响应的数据附加到 window.name
上。由于现在 A 和 B 还不同源,A 依旧不能获取到 B 的 name
属性。当B 获取到数据之后,再将页面导航到任何一个与 A 同源的页面,这时 A 就可以直接获取到 B 的 name
属性值。当 A 获取到数据之后,就可以随时删掉 B。
主页面代码:
// http://www.myapp.com:3000/demo4
function sendMsg(msg) {
var state = 0, data;
var frame = document.createElement("frame");
var baseProxy = "http://www.otherapp.com:3000/demo4-req";
var request = {data:msg};
frame.src = baseProxy + "#" + encodeURI(JSON.stringify(request));
frame.style.display = "none";
frame.onload = function(){
if(state === 1){
data = frame.contentWindow.name;
document.querySelector('.res').innerHTML = "获得响应:" + data;
//删除iframe
frame.contentWindow.document.write('');
frame.contentWindow.close();
document.body.removeChild(frame);
} else {
state = 1;
frame.src = "http://www.myapp.com:3000/demo4-res";
}
};
document.body.appendChild(frame);
}
document.querySelector('button').onclick = function (){
var val = Math.random();
sendMsg(val);
document.querySelector('.val').innerHTML = "请求数据:"+val;
}
目标页面代码:
// http://www.otherapp.com:3000/demo4-res
var hash = window.location.hash;
if(hash && hash.length>1){
var request = hash.substring(1, hash.length);
var obj = JSON.parse(decodeURI(request));
var data = obj.data;
//数据乘以100
window.name = data*100;
}
这个例子也是将请求的数据放在hash中传入其他域的目标页面,目标页面将数据乘100后设置到window.name中,然后跳转到与主页面同域的页面,这样主页面就可以从window.name中获取结果了。效果如下:
window.postMessage(message, targetOrigin)
可以用于安全跨域通信。当该方法被调用时,将分发一个消息事件,如果窗口监听了相应的消息,窗口就可以获取到消息和消息来源。如下图所示:window.postMessage
来发送消息。同时,它也将监听回馈消息:
// http://www.otherapp.com:3000/demo5-b
function postMessage(msg){
var targetWindow = parent.window;
targetWindow.postMessage(msg,"*");
}
function handleReceive(msg){
if(msg.data == "ok"){
//要做的事在这
}else{
//重新发送消息
postMessage(JSON.stringify({color:'red'}));
}
}
window.addEventListener("message", handleReceive, false);
window.onload = function(){
postMessage(JSON.stringify({color:'red'}));
}
父窗口监听了消息事件,当消息到达时,它首先检查消息是否是来 www.otherapp.com,如果是就发送一个反馈消息。
// http://www.myapp.com:3000/demo5
function handleReceive(event){
if(event.origin != "http://www.otherapp.com:3000") return;
//处理数据
var data = JSON.parse(event.data);
document.querySelector('div').innerHTML = "来自iframe的颜色:"+data.color;
var otherAppFrame = window.frames["otherApp"]
otherAppFrame.postMessage("ok","http://www.otherapp.com:3000");
}
window.addEventListener("message", handleReceive, false);
至此,所有关于跨域通信的到此结束,如果你还有好的方案请留言哦。
-
上一个: js中利用JSONP解决跨域问题
-
下一个: js中Promise的使用例子详细介绍
相关文章
- JS跨域请求外部服务器的资源 03-16
- HTML简单购物数量小程序代码展示 10-31
- html canvas实现弹幕功能 10-31
- HTML中空格表示的意义 10-31
- html area标签解读 10-31
- html使用表单标签实现注册页面代码展示 10-31