跨域 Iframe 通信解决方案(兼容 IE 系列浏览器。)

实现思路:

1、postMessage(IE8+, Firefox 3.1+, Opera 9+, Safari, and Chrome)

2、利用window.navigator共享信息,使支持IE6,IE7

i、父窗口向子窗口iframe发送信息:

               document.getElementById("childiframe").contentWindow .postMessage(
"我是父窗口",
"http://child.com:8080" //可以*通配符代替,表示支持所有域
);

上面的代码表示父窗口向子iframe:childiframe,域名为"http://child.com:8080"  发送 "我是父窗口"的消息

ii、子iframe

               window.addEventListener("message", function( event ) {
// 把父窗口发送过来的数据显示在子窗口中
document.getElementById("content").innerHTML+=event.data+"<br/>";
}, false );

iii、父窗口如果有多个子iframe,那么父窗口可以向多个子窗口发送消息

利用Object-orient-programing  ,父窗口和多个子窗口分别实例化一个Message对象,各个窗口的message对象里开辟一个内存可以保存多个目标对象Target,意思是要发送消息到这些目标,

Target对象实现自己的send方法 ,send考虑到浏览器的兼容性,Target对象里保存了target和name信息,target表示要发送的窗口,name是发送目标的名称 ,name的作用仅仅是支持IE6、7中使用到(在window.navigator标示一个唯一send的回调函数)

     var prefix = "arale-messenger",
        supportPostMessage = 'postMessage' in window;
// Target 类, 消息对象
function Target(target, name){
var errMsg = '';
if(arguments.length < 2){
errMsg = 'target error - target and name are both required';
} else if (typeof target != 'object'){
errMsg = 'target error - target itself must be window object';
} else if (typeof name != 'string'){
errMsg = 'target error - target name must be string type';
}
if(errMsg){
throw new Error(errMsg);
}
this.target = target;
this.name = name;
} // 往 target 发送消息, 出于安全考虑, 发送消息会带上前缀
if ( supportPostMessage ){
// IE8+ 以及现代浏览器支持
Target.prototype.send = function(msg){
this.target.postMessage(prefix + msg, '*');
};
} else {
// 兼容IE 6/7 利用window.navigator共享信息,使支持IE6,IE7
Target.prototype.send = function(msg){
var targetFunc = window.navigator[prefix + this.name];
if ( typeof targetFunc == 'function' ) {
targetFunc(prefix + msg, window);
} else {
throw new Error("target callback function is not defined");
}
};
}

iiii: 每个窗口都实例化的Message类:

targets 里保存目标发送对象,name当前窗口的名字,最后会传给Target,也是只在兼容IE6、7中用到。

listenFunc :保存监听的回调,一个页面可以实现多个监听。

initListen :ie6、7中保存全局回调函数,以方便在Target的send中触发

IE8+和现代化浏览器中监听message事件。

    // 信使类
// 创建Messenger实例时指定, 必须指定Messenger的名字, (可选)指定项目名, 以避免Mashup类应用中的冲突
// !注意: 父子页面中projectName必须保持一致, 否则无法匹配
function Messenger(messengerName, projectName){
this.targets = {};
this.name = messengerName;
this.listenFunc = [];
prefix = projectName || prefix;
this.initListen();
} // 添加一个消息对象
Messenger.prototype.addTarget = function(target, name){
var targetObj = new Target(target, name);
this.targets[name] = targetObj;
}; // 初始化消息监听
Messenger.prototype.initListen = function(){
var self = this;
var generalCallback = function(msg){
if(typeof msg == 'object' && msg.data){
msg = msg.data;
}
// 剥离消息前缀
msg = msg.slice(prefix.length);
for(var i = 0; i < self.listenFunc.length; i++){
self.listenFunc[i](msg);
}
}; if ( supportPostMessage ){
if ( 'addEventListener' in document ) {
window.addEventListener('message', generalCallback, false);
} else if ( 'attachEvent' in document ) {
window.attachEvent('onmessage', generalCallback);
}
} else {
// 兼容IE 6/7
window.navigator[prefix + this.name] = generalCallback;
}
}; // 监听消息
Messenger.prototype.listen = function(callback){
this.listenFunc.push(callback);
};
// 注销监听
Messenger.prototype.clear = function(){
this.listenFunc = [];
};
// 广播消息
Messenger.prototype.send = function(msg){
var targets = this.targets,
target;
for(target in targets){
if(targets.hasOwnProperty(target)){
targets[target].send(msg);
}
}
};

完整demo:

跨域 Iframe 通信解决方案(兼容 IE 系列浏览器。)

完整代码:

message.js

(function(w){
// 消息前缀, 建议使用自己的项目名, 避免多项目之间的冲突
var prefix = "arale-messenger",
supportPostMessage = 'postMessage' in window; // Target 类, 消息对象
function Target(target, name){
var errMsg = '';
if(arguments.length < 2){
errMsg = 'target error - target and name are both required';
} else if (typeof target != 'object'){
errMsg = 'target error - target itself must be window object';
} else if (typeof name != 'string'){
errMsg = 'target error - target name must be string type';
}
if(errMsg){
throw new Error(errMsg);
}
this.target = target;
this.name = name;
} // 往 target 发送消息, 出于安全考虑, 发送消息会带上前缀
if ( supportPostMessage ){
// IE8+ 以及现代浏览器支持
Target.prototype.send = function(msg){
this.target.postMessage(prefix + msg, '*');
};
} else {
// 兼容IE 6/7
Target.prototype.send = function(msg){
var targetFunc = window.navigator[prefix + this.name];
if ( typeof targetFunc == 'function' ) {
targetFunc(prefix + msg, window);
} else {
throw new Error("target callback function is not defined");
}
};
} // 信使类
// 创建Messenger实例时指定, 必须指定Messenger的名字, (可选)指定项目名, 以避免Mashup类应用中的冲突
// !注意: 父子页面中projectName必须保持一致, 否则无法匹配
function Messenger(messengerName, projectName){
this.targets = {};
this.name = messengerName;
this.listenFunc = [];
prefix = projectName || prefix;
this.initListen();
} // 添加一个消息对象
Messenger.prototype.addTarget = function(target, name){
var targetObj = new Target(target, name);
this.targets[name] = targetObj;
}; // 初始化消息监听
Messenger.prototype.initListen = function(){
var self = this;
var generalCallback = function(msg){
if(typeof msg == 'object' && msg.data){
msg = msg.data;
}
// 剥离消息前缀
msg = msg.slice(prefix.length);
for(var i = 0; i < self.listenFunc.length; i++){
self.listenFunc[i](msg);
}
}; if ( supportPostMessage ){
if ( 'addEventListener' in document ) {
window.addEventListener('message', generalCallback, false);
} else if ( 'attachEvent' in document ) {
window.attachEvent('onmessage', generalCallback);
}
} else {
// 兼容IE 6/7
window.navigator[prefix + this.name] = generalCallback;
}
}; // 监听消息
Messenger.prototype.listen = function(callback){
this.listenFunc.push(callback);
};
// 注销监听
Messenger.prototype.clear = function(){
this.listenFunc = [];
};
// 广播消息
Messenger.prototype.send = function(msg){
var targets = this.targets,
target;
for(target in targets){
if(targets.hasOwnProperty(target)){
targets[target].send(msg);
}
}
}; w["Messenger"]=Messenger;
})(window);

child.html:

<!doctype html>
<html>
<head>
<script type="text/javascript" src="message.js"></script>
<script>
window.onload=function(){
var messenger = new Messenger('iframe1', 'MessengerProject');
messenger.addTarget(window.parent, 'parent');
messenger.targets['parent'].send('发给父页面的消息');
messenger.listen(function(msg) {
document.getElementById("msg").innerHTML=msg;
});
}
</script>
</head>
<body>
child
<div id="msg"></div>
</body>
</html>

parent.html

<!doctype html>
<html>
<head>
<script type="text/javascript" src="message.js"></script>
<script>
window.onload=function(){
var messenger = new Messenger('parent', 'MessengerProject');
var iframe1=window.iframe1;
messenger.addTarget(iframe1.contentWindow, 'iframe1');
messenger.targets['iframe1'].send('发给子页面1的消息');
messenger.listen(function(msg) {
document.getElementById("msg").innerHTML=msg;
});
}
</script>
</head>
<body>
parent
<div id="msg"></div>
<iframe id="iframe1" src="child.html" width=100 height=100>
</body>
</html>
上一篇:从协议VersionedProtocol开始


下一篇:Java2_Java泛型