Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 410|回复: 0

跨域解决方案之HTML5 postMessage

[复制链接]
  • TA的每日心情
    奋斗
    昨天 16:00
  • 签到天数: 755 天

    [LV.10]以坛为家III

    2034

    主题

    2092

    帖子

    70万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    707348
    发表于 2021-4-23 11:16:27 | 显示全部楼层 |阅读模式

    问题场景:

    web是嵌入到手机客户端中的静态页面,为了统计用户行为需要引入ga,但是ga必须是在www下才行,哪怕是localhost,这就是矛盾。解决方案是在页面中使用iframe,iframe是在另外一个域名下的,然后在iframe中调用ga方法。很显然必须要解决iframe的跨域通信。

    var frame=document.getElementById("gaFrame");
        document.body.onclick=function(){
            var sendData={
                "name":"deals_list",
                "event":"deals_click",
                "e_data":"这是发送的数据"
            }
            frame.contentWindow.postMessage(sendData,"*")
        }

    每次点击指定区域时候向iframe中发送消息,然后在iframe中监听消息数据,发送ga。

    var OnMessage = function(e) {
             var data=e.data;
             ga('send', 'pageview',"/"+data);
         }
    
         function init() {
             if (window.addEventListener) { // all browsers except IE before version 9
                 window.addEventListener("message", OnMessage, false);
             } else {
                 if (window.attachEvent) { // IE before version 9
                     window.attachEvent("onmessage", OnMessage);
                 }
             }
         };
         init();

    好,实际场景和方法介绍完了,开工学习相关知识。

    window.postMessage

    window.postMessage 是一个用于安全的使用跨源通信的方法。通常,不同页面上的脚本只在这种情况下被允许互相访问,当且仅当执行它们的页面所处的位置使用相同的协议(通常都是 http)、相同的端口(http默认使用80端口)和相同的主机(两个页面的 document.domain 的值相同)。 在正确使用的情况下,window.postMessage 提供了一个受控的机制来安全地绕过这一限制。

    window.postMessage, 调用时,挂起的脚本必须执行完成才会将 MessageEvent 派遣至目标window (例如:如果一个事件处理程序调用了window.postMessage,剩余的事件处理程序就会挂起超时等).  MessageEvent 有消息类型, 它被设置为第一个参数值提供给window.postMessage的data属性, 对应的window调用window.postMessage的时候,window.postMessage主文档的来源的origin属性被称为源属性,指哪个调用window.postMessage的窗口。 (事件的其他标准属性都存在与对应的预期值.)

    语法:

    otherWindow.postMessage(message, targetOrigin);
    otherWindow
    引用另外一个窗口,比如上面实例中的iframe,contentWindow 是iframe中的window对象。
    message
    发送到其他window中的数据

    targetOrigin
    目标源,可以限定只接收来自某个URL下的数据

    监听发送事件
    window.addEventListener("message", receiveMessage, false);
    
    function receiveMessage(event)
    {
      if (event.origin !== "http://example.org:8080")
        return;
    
      // ...
    }

    data:来自其他window的数据。

    origin:调用postMessage的窗口url。

    source:发送消息窗口的引用。可以使用该方法使来自不同源的窗口进行双向通信。

    安全性

     

    var popup = window.open(...popup details...);
    
    // When the popup has fully loaded, if not blocked by a popup blocker:
    
    // This does nothing, assuming the window hasn't changed its location.
    popup.postMessage("The user is 'bob' and the password is 'secret'",
                      "https://secure.example.net");
    
    // This will successfully queue a message to be sent to the popup, assuming
    // the window hasn't changed its location.
    popup.postMessage("hello there!", "http://example.org");
    
    function receiveMessage(event)
    {
      // Do we trust the sender of this message?  (might be
      // different from what we originally opened, for example).
      if (event.origin !== "http://example.org")
        return;
    
      // event.source is popup
      // event.data is "hi there yourself!  the secret response is: rheeeeet!"
    }
    window.addEventListener("message", receiveMessage, false);

     

    /*
     * In the popup's scripts, running on <http://example.org>:
     */
    
    // Called sometime after postMessage is called
    function receiveMessage(event)
    {
      // Do we trust the sender of this message?
      if (event.origin !== "http://example.com:8080")
        return;
    
      // event.source is window.opener
      // event.data is "hello there!"
    
      // Assuming you've verified the origin of the received message (which
      // you must do in any case), a convenient idiom for replying to a
      // message is to call postMessage on event.source and provide
      // event.origin as the targetOrigin.
      event.source.postMessage("hi there yourself!  the secret response " +
                               "is: rheeeeet!",
                               event.origin);
    }
    
    window.addEventListener("message", receiveMessage, false);

    在web worker是中使用postMessage和onMessage

    主线程中创建 Worker 实例,并监听 onmessage 事件
    <html> 
     <head> 
     <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> 
     <title>Test Web worker</title> 
     <script type="text/JavaScript"> 
         function init(){ 
             var worker = new Worker('compute.js'); 
             //event 参数中有 data 属性,就是子线程中返回的结果数据
             worker.onmessage= function (event) { 
                 // 把子线程返回的结果添加到 div 上
                 document.getElementById("result").innerHTML += 
                    event.data+"<br/>"; 
             }; 
         } 
     </script> 
     </head> 
     <body onload="init()"> 
     <div id="result"></div> 
     </body> 
     </html>

    在客户端的 compute.js 中,只是简单的重复多次加和操作,最后通过 postMessage 方法把结果返回给主线程,目的就是等待一段时间。而在这段时间内,主线程不应该被阻塞,用户可以通过拖拽浏览器,变大缩小浏览器窗口等操作测试这一现象。这个非阻塞主线程的结果就是 Web Workers 想达到的目的。

    compute.js 中调用 postMessage 方法返回计算结果
    var i=0; 
    
     function timedCount(){ 
         for(var j=0,sum=0;j<100;j++){ 
             for(var i=0;i<100000000;i++){ 
                 sum+=i; 
             } 
         } 
         // 调用 postMessage 向主线程发送消息
         postMessage(sum); 
     } 
    
     postMessage("Before computing,"+new Date()); 
     timedCount(); 
     postMessage("After computing,"+new Date());

     

     

     
    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-6-27 17:13 , Processed in 0.058052 second(s), 30 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表