问题场景:

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

  1. var frame=document.getElementById("gaFrame");
  2. document.body.onclick=function(){
  3. var sendData={
  4. "name":"deals_list",
  5. "event":"deals_click",
  6. "e_data":"这是发送的数据"
  7. }
  8. frame.contentWindow.postMessage(sendData,"*")
  9. }

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

  1. var OnMessage = function(e) {
  2. var data=e.data;
  3. ga('send', 'pageview',"/"+data);
  4. }
  5.  
  6. function init() {
  7. if (window.addEventListener) { // all browsers except IE before version 9
  8. window.addEventListener("message", OnMessage, false);
  9. } else {
  10. if (window.attachEvent) { // IE before version 9
  11. window.attachEvent("onmessage", OnMessage);
  12. }
  13. }
  14. };
  15. 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的窗口。 (事件的其他标准属性都存在与对应的预期值.)

语法:

  1. otherWindow.postMessage(message, targetOrigin);
  1. otherWindow
    引用另外一个窗口,比如上面实例中的iframecontentWindow iframe中的window对象。
  1. message
    发送到其他window中的数据
  2.  
  3. targetOrigin
    目标源,可以限定只接收来自某个URL下的数据
  4.  
  5. 监听发送事件
  1. window.addEventListener("message", receiveMessage, false);
  2.  
  3. function receiveMessage(event)
  4. {
  5. if (event.origin !== "http://example.org:8080")
  6. return;
  7.  
  8. // ...
  9. }

data:来自其他window的数据。

origin:调用postMessage的窗口url。

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

安全性

  1. var popup = window.open(...popup details...);
  2.  
  3. // When the popup has fully loaded, if not blocked by a popup blocker:
  4.  
  5. // This does nothing, assuming the window hasn't changed its location.
  6. popup.postMessage("The user is 'bob' and the password is 'secret'",
  7. "https://secure.example.net");
  8.  
  9. // This will successfully queue a message to be sent to the popup, assuming
  10. // the window hasn't changed its location.
  11. popup.postMessage("hello there!", "http://example.org");
  12.  
  13. function receiveMessage(event)
  14. {
  15. // Do we trust the sender of this message? (might be
  16. // different from what we originally opened, for example).
  17. if (event.origin !== "http://example.org")
  18. return;
  19.  
  20. // event.source is popup
  21. // event.data is "hi there yourself! the secret response is: rheeeeet!"
  22. }
  23. window.addEventListener("message", receiveMessage, false);
  1. /*
  2. * In the popup's scripts, running on <http://example.org>:
  3. */
  4.  
  5. // Called sometime after postMessage is called
  6. function receiveMessage(event)
  7. {
  8. // Do we trust the sender of this message?
  9. if (event.origin !== "http://example.com:8080")
  10. return;
  11.  
  12. // event.source is window.opener
  13. // event.data is "hello there!"
  14.  
  15. // Assuming you've verified the origin of the received message (which
  16. // you must do in any case), a convenient idiom for replying to a
  17. // message is to call postMessage on event.source and provide
  18. // event.origin as the targetOrigin.
  19. event.source.postMessage("hi there yourself! the secret response " +
  20. "is: rheeeeet!",
  21. event.origin);
  22. }
  23.  
  24. window.addEventListener("message", receiveMessage, false);

在web worker是中使用postMessage和onMessage

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

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

compute.js 中调用 postMessage 方法返回计算结果
  1. var i=0;
  2.  
  3. function timedCount(){
  4. for(var j=0,sum=0;j<100;j++){
  5. for(var i=0;i<100000000;i++){
  6. sum+=i;
  7. }
  8. }
  9. // 调用 postMessage 向主线程发送消息
  10. postMessage(sum);
  11. }
  12.  
  13. postMessage("Before computing,"+new Date());
  14. timedCount();
  15. postMessage("After computing,"+new Date());
  1.  

跨域解决方案之HTML5 postMessage的更多相关文章

  1. html5跨域数据传递(postMessage)

    在html5中有个支持跨域传递的方法postMessage,可是实现iframe之间的数据传递! 代码如下:数据发送页面 <!DOCTYPE HTML> <html lang=&qu ...

  2. JSON跨域解决方案收集

    最近面试问的挺多的一个问题,就是JavaScript的跨域问题.在这里,对跨域的一些方法做个总结.由于浏览器的同源策略,不同域名.不同端口.不同协议都会构成跨域:但在实际的业务中,很多场景需要进行跨域 ...

  3. js最全的十种跨域解决方案

    在客户端编程语言中,如javascript和ActionScript,同源策略是一个很重要的安全理念,它在保证数据的安全性方面有着重要的意义.同 源策略规定跨域之间的脚本是隔离的,一个域的脚本不能访问 ...

  4. web跨域解决方案

    阅读目录 什么是跨域 常用的几种跨域处理方法: 跨域的原理解析及实现方法 总结 摘要:跨域问题,无论是面试还是平时的工作中,都会遇到,本文总结处理跨域问题的几种方法以及其原理,也让自己搞懂这方面的知识 ...

  5. iframe跨域解决方案

    公司某个功能用的是iframe,由于跨域的原因,我们不能直接设置父级页面iframe的高度,所以用了一个中间页home来完成父级页面iframe的高度设置,这种中间页其实很多时候不好用,因为涉及到页面 ...

  6. Atitit.js跨域解决方案attilax大总结 后台java php c#.net的CORS支持

    Atitit.js跨域解决方案attilax大总结 后台java php c#.net的CORS支持 1. 设置 document.domain为一致  推荐1 2. Apache 反向代理 推荐1 ...

  7. localStorage和cookie的跨域解决方案

    原文转自:点我 前言 localStorage和cookie大家都用过,我前面也有文章介绍过,跨域大家也都了解,我前面也有文章详细描述过.但是localStorage和cookie的跨域问题,好多小伙 ...

  8. 跨域解决方案一:使用CORS实现跨域

    跨站HTTP请求(Cross-site HTTP request)是指发起请求的资源所在域不同于请求指向的资源所在域的HTTP请求. 比如说,我在Web网站A(www.a.com)中通过<img ...

  9. asp.net web api2.0 ajax跨域解决方案

    asp.net web api2.0 ajax跨域解决方案 Web Api的优缺点就不说了,直接说怎么跨域,我搜了一下,主要是有两种.  一,ASP.NET Web API支持JSONP,分两种 1, ...

随机推荐

  1. 使用记忆化优化你的 R 代码

    目录 使用记忆化优化你的 R 代码 R 中的性能优化 R 何时变慢 R 何时变(更)快 R 中的记忆化 何时使用记忆化 使用记忆化优化你的 R 代码 本文翻译自<Optimize your R ...

  2. java操作html格式数据

    近期在做数据抓取功能,抓取到的数据为html格式,需在后台进行转换后取值,为了避免使用字符串查找方式获取而使用Jsonp完美实现. 1. 引入Jsonp: <dependency> < ...

  3. 求一个n元一次方程的解,Gauss消元

    求一个n元一次方程的解,Gauss消元 const Matrix=require('./Matrix.js') /*Gauss 消元 传入一个矩阵,传出结果 */ function Gauss(mat ...

  4. android 企业级高性能图表库 SciChart (付费)

    1.官网 https://www.scichart.com/ 2.特性 2.1 链接 https://www.scichart.com/android-chart-features/ https:// ...

  5. element-ui 使用span-method表格合并后hover样式的处理

    在使用element表格合并后,发现鼠标只有移入第一个合并行时,合并的部分会高亮,移入其他行,不会高亮,这样效果看起来不是很好.查看了文档也没有直接的解决方法,就通过现有的方法处理了一下,解决了hov ...

  6. vue使用nprogress页面加载进度条

    vue使用nprogress页面加载进度条 NProgress是页面跳转是出现在浏览器顶部的进度条 官网:http://ricostacruz.com/nprogress/ github:https: ...

  7. Angular 2 升级到 Angular 5

    Angular 2 升级到 Angular 5 ts文件最上面的import语句里不要添加 .ts 后缀 , 不然 npm start 编译会失败 . 虽然浏览器能打开项目的URL , 但是内容会丢失 ...

  8. PyCharm | 常见问题

    1.安装使用 每次建立PyCharm工程都建立一个虚拟环境env,需要重新下载或复制模块

  9. CoreJava笔记之线程

    程序,进程和线程程序:没有执行的指令序列和相关的数据的集合(如:qq.exe) 如:磁盘上的可执行命令进程:正在执行的程序,进程占用资源(CPU,Memoary,IO)线程:是进程中并发执行的过程(共 ...

  10. Android使用7牛云存储

    第一次使用这个云存储,话说7牛云存储大有来头!区别于国内外其他云存储,七牛自行研发的全分布式架构解决了其他云存储单一数据中心架构可能存在的风险,同时首创双向加速特性对数据上传下载均加速,使得数据访问速 ...