• 跨域 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:

       

         完整代码:

         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> 
    
  • 相关阅读:
    滤波和减采样的互换
    LwIP情景示例
    [redis] redis 对string类型数据操作
    [ExtJs] ExtJs4.2 数据模型Ext.data.Model学习
    [生活] 90年前后出生的人现状如何?
    【java】java内存模型(2)--volatile内存语义详解
    【java】java内存模型 (1)--基础
    [extjs] ExtJS 4.2 开发环境搭建
    强烈推荐:240多个jQuery插件
    使用CXF为webservice添加拦截器
  • 原文地址:https://www.cnblogs.com/liuminghai/p/4441962.html
Copyright © 2020-2023  润新知