iframe跨域JS通讯
文章目录
记录自己在遇到JS父子框架跨域通讯问题的解决.
原来我博客就一个域名,后面换成多域名了.
我现在登陆时单独一个域名.
博客主域名: www.getce.cn
博客登陆域名: login.getce.cn
所以交互的时候要扯到跨域的问题.
不跨域通讯
原来不跨越非常简单.
子框架访问父框架
// 访问父框架变量,
// 或者window.parent.user .
// parent上一级,top就是最顶级.
console.log(window.top.user);
//调用父框架的函数
window.top.abc();
父框架访问子框架
sub_window = window.frames["sub_id"]; //获得window对象
//用法
sub_window.document.body.innerHTML //获取子框架源码
sub_window.test(); //调用子框架中test函数.
跨域通讯
网上最常见的方案就是设置document.domain 但是我实际测试没效果....
于是我用了postMessage 消息机制通讯. 这可能是win api抄过来的概念....
postMessage不但可以用于跨域,不跨域也可以.
注册监听函数
//回调函数
function receiveMessage(event){
//event就是另外窗口传过来的. 支持数组,对象,还有基本变量类型.
}
window.addEventListener("message", receiveMessage, false);
如果双向通讯那么子父框架都需要自己都注册监听.
当收到消息会自动进入回调函数,
发送消息
子框架向父框架发送字符串.
window.parent.postMessage("hi","https://www.getce.cn");
window.parent 就是父窗口的window对象.
第二个参数的域名就是父框架的域名,带协议.
反过来也是.
父框架给子框架发,给兄弟框架发也是.
先获取window对象.然后接postMessage.
sub_window = window.frames["sub_id"];
sub_window.postMessage("ok","https://login.getce.cn");
第一个参数是 需要传递的变量或者对象,或者数组.
第二个参数是 对方的带协议的域名.
处理消息
function receiveMessage(event)
{
console.log('接到站点的消息:');
console.log(event.origin); //控制台打印 来自哪个域名发来的消息.
//判断是否是自己子框架发来的,如果不是就不处理.
if (event.origin.indexOf("getce.cn") == -1){
return;
}
console.log(event.source); //来源页面
console.log(event.data); //发送过来的数据
//如果发来的是字符串"ok",那么返回一个 hi.
//直接可以用event.source发消息.直接回复.
if (event.data == "ok"){
event.source.postMessage("hi","https://login.getce.cn");
}
}
取消监听
window.removeEventListener("message", receiveMessage, false);
实际应用
本博客博文下面的登陆就是.
如果没有登陆的话,任意博文下面,
编辑框有个登陆按钮.
点登陆实际上打开了一个跨域的登陆页面.
此时父框架监听子框架消息(因为需求简单,只需要单向通讯)
用户登陆后,站点是有cookie的.但是父框架如果不刷新,或者不处理,是无法知道已经登陆的.
这时候,子框架(登陆页面)将用户信息传给父框架,那么父接收用户信息后就知道已经登陆了.即可免刷新登陆.