• iframe跨域通信实战


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

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

    简介

    项目实战中postMessage的使用

    问题描述

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

    • iframe跨域通信
    • 他们重新做一套(不可取的备选)
    • 我们来实现他们的点评业务(业务交错不可取)

    杂货铺中的知识点

    很明显我们更倾向于第一种方式,仿佛记得之前总结过类似的一篇文章同源策略和跨域知识点学习,当时完全是参考知识点进行的一次搬移,现在看来完全还是没有透彻理解。

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

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

    实战知识点

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

    /**
     * 页面跳转方法
     * @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内做特殊处理

    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事件获取我传递过去的消息做特殊处理即可

    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/

  • 相关阅读:
    Mybatis的property与用户名密码等jdbc连接信息配置方式(一)使用properties文件
    Mybatis的#和$的区别
    Spring的依赖注入两种方式之一:setter注入
    Mybatis传递参数的各种方式:简单类型,@Param,map,java对象等等
    "蔚来杯"2022牛客暑期多校训练营2 KLink with Bracket Sequence I
    Villages: Landlines
    "蔚来杯"2022牛客暑期多校训练营1 D Mocha and Railgun
    3436403213password is internal pc
    test
    东方电气新进实力股东名单
  • 原文地址:https://www.cnblogs.com/unofficial/p/7553253.html
Copyright © 2020-2023  润新知