iframe跨域通讯实战

"长时间不写文章,开头的方式老是那么出奇的类似",最近很忙,很久没写博客了啊(是否是?)。
更换工做已经有三个月有余,这段三个月把过去三年没加过的班都加了一次。收获挺多,发现的问题也挺多。
一直也在思考一些问题:
如何把本身碰见的问题好好的理解而且总结?
如何很好的学习新知识,不仅是停留在用的基础上?
……segmentfault

上面的问题我一直在尝试更适合个人方法,暂时就不扯淡了,先尝试一下把这段时间过程当中碰见的问题总结下,而后争取给看文的你以个人方式描述清楚,我想我应该就把第一个问题解决了。跨域

简介

项目实战中postMessage的使用app

问题描述

前提:咱们的项目与兄弟团队的项目都是基于同一套基础框架开发,只是在视图层咱们有各自的一套东西。
项目是一个hybrid项目,目前是以h5的形式在开发,后期能够轻松转为hybrid。目前已经以h5的形式上线到自家公众号,大体是在硬件上产出一份报告,h5把报告的内容展现出来。
新需求是,把报告推给兄弟团队的APP,在APP内也能打开咱们的报告进行查看报告而后点评。
兄弟团队为了最小的改动实现这个功能,用了iframe的形式打开咱们推过去的报告连接,问题就出在报告能在兄弟团队的APP中打开却不能跳转连接,问题是由于咱们的基础框架提供的forward方法在app内是经过native的方式来跳转,可是咱们的协议不会被兄弟团队的app识别,简单说就是跳转直接被拦截了。
通过几番商量,商定出三个解决方案:框架

  • iframe跨域通讯
  • 他们从新作一套(不可取的备选)
  • 咱们来实现他们的点评业务(业务交错不可取)

杂货铺中的知识点

很明显咱们更倾向于第一种方式,仿佛记得以前总结过相似的一篇文章同源策略和跨域知识点学习,当时彻底是参考知识点进行的一次搬移,如今看来彻底仍是没有透彻理解。post

  • 同源:同源即须要协议主机名(域名或者ip)端口相同。
  • 跨域:域名不一致了,天然是不一样源的,这种状况下要通讯何解呢?

postMessage派上用途。
h5模式下子页面跳转协议能够正常使用history模式或者非单页模式跳转。(知识点:这种状况下iframe的src不会随iframe内跳转连接的变化而变化,父页面不能监听到子页面内的页面变化)
hybrid模式下连接跳转被拦截,页面表现就是连接点不了,如何让父元素知道我点了什么连接,而后来切换页面,他们作url更换,来实现跳转而且支持切换页面操做,如此咱们就须要子页面给父页面发送一条message告诉它我要跳转到哪个页面。学习

实战知识点

页面跳转中咱们使用了$forward方法进行收口,全部的跳转都须要通过这个方法(对于收口的好处这里就体现出来了),我只须要判断ua在跳转前执行如下消息发送的方法。this

/**
 * 页面跳转方法
 * @param page 要跳转的页面名称
 * @param param 跳转时须要额外携带的参数
 */
$forward(page, param) {
    // _ extend getUrlParam getUrlRule loadPage isHybrid 省略
    var param = _.extend(_.getUrlParam(), param);
    let url = _.getUrlRule(page, param);
    if(isHybrid) {
        _.requestHybrid({
            // 省略
        });
    } else {
        _.loadPage(url);
    }
}

在跳转前咱们先检测一下ua,判断是不是在兄弟团队app内作特殊处理url

let ua = navigator.userAgent.toLowerCase(),
    isFriendHybrid = /friend_hybrid_\w+_(\d*\.?)+/.test(ua);
if(isFriendHybrid) {
    window.top.postMessage({
        tag: 'forward',
        url: url
    }, '*')
} else {
    this.$forward();
}

在兄弟团队的父页面只须要监听message事件获取我传递过去的消息作特殊处理便可.net

window.addEventListener('message', function(e) {
    console.log(e.data);
    // {tag: 'forward', url: ……}
})

例如在一个特殊位置我会在没有pdf的时候直接弹出调试“暂时没有报告”,用户点击之际显示的是我弹出的toast,因为嵌入后有兼容问题,因而咱们又约定了一个方法。调试

window.top.postMessage({
    tag: 'showtoast',
    content: '暂时没有报告'
}, '*')

这应该就是一个典型的iframe跨域通讯例子。

demo

https://jsfiddle.net/unofficial/xwaksbvn/

相关文章
相关标签/搜索