zoukankan      html  css  js  c++  java
  • 封装一个postMessage库,进行iframe跨域交互

    这是近期个人在开发chrome插件时的其中一个小总结。还有很多没有总结出来。因为目前插件还在迭代中,(herry菌插件,用于B站C站),属于个人业余的一个小项目。还有很多功能没有实现,以及还需要再看能加上什么功能。

    封装的postMessage库 herryPostMessage.js

    (function (w) {
      //herry对象
      w.herry = {};
      //iframe的id
      if(!herry.iframeId) {
        herry.iframeId = 'iframe'
      }
      //父窗口名字
      if(!herry.parentName) {
        herry.parentName = '父窗口'
      }
      //子窗口名字
      if(!herry.childName) {
        herry.childName = '子窗口'
      }
      //跨域对象
      const messageObj = {};
      //父页面
      /**
       * 发送给子页面数据
       */
      const postMessage = (data, fn = null) => {
        const iframe = document.getElementById(herry.iframeId)
        iframe.contentWindow.postMessage(
          {
            name: herry.parentName, //父页面名字
            ...data,
          },
          "*"
        );
        messageObj[data.action] = fn;
      };
      /**
       * 监听子页面返回的数据
       */
       w.addEventListener(
        "message",
        (event) => {
          const { data } = event;
          if (data && typeof data === "object" && data.name === herry.childName) {
            messageObj[data.action](data);
          }
        },
        false
      );
      //子页面
      /**
       * 返回数据给父页面 参1=当前action 参2=返回的数据
       */
      const returnData = (action, data) => {
        top.postMessage(
          {
            name: herry.childName, //子页面名字
            action,
            data,
          },
          "*"
        );
      };
      /**
       * 监听父页面发送的数据
       */
       w.addEventListener(
        "message",
        async (event) => {
          const { data } = event;
          if (data && typeof data === "object" && data.name === herry.parentName) {
            if (herry.callback) {
              herry.callback(data)
            }
          }
        },
        false
      );
      herry.postMessage = postMessage;
      herry.returnData = returnData;
    })(window);

    使用这个库让a域名下获取b域名下的数据,即a发出请求,b返回给a数据a是父页面,b是子页面

    使用:

    域名a和b的页面上都需要引入herryPostMessage.js

    a页面处理(父页面):

    加入iframe(src是b域名的页面,需要设置一个id,一般也可以将iframe使用样式隐藏掉)。

    <iframe
      src="//b.com/xxx.html"
      id="ifr"
      frameborder="0"
    ></iframe>

    设置iframeId=上面的这个id:

    herry.iframeId = "ifr";

    发起请求(action是设置的一个请求名,在b页面中进行匹配用。后面的数据是携带给b页面用的参数。后面的res是b页面执行后的回调函数,可进行处理b返回的数据):

    herry.postMessage({ action:'geta1', x: 1 }, (res) => {
      console.log(res.data);
    });

    b页面处理(子页面):

    b页面的herry.callback通过action匹配执行,并做处理,通过herry.returnData将数据返回给a的回调函数。即实现了交互。

    herry.callback = async (data) => {
      if (data.action === "geta1") {
        //...
        herry.returnData(data.action, { x: 2 });
      }
      //...
    };

    不过这种封装方式也不是特别好,有局限性,比如b(子页面)像a(父页面)发起请求还是比较麻烦。欢迎各位提出意见或建议。

    欢迎一起交流!
    【http://wuhairui.cnblogs.com/】

  • 相关阅读:
    c/c++ # and ## in macros以及宏debug
    postgresql unnamed statement
    postgresql/lightdb a [left/right] join b on true的含义
    openjdk、javafx各发行版
    lightdb for postgresql PL/pgSQL perform、execute、call区别
    postgresql有mysql兼容插件吗?
    各种互联网公司,不要再那么没有分寸的刷屏QPS/TPS/日活千万这些毫无意义的数据了
    PostgreSQL分布式数据库实践
    LightDB发布日常运维管理手册
    恒生电子发布金融分布式数据库LightDB
  • 原文地址:https://www.cnblogs.com/wuhairui/p/14595893.html
Copyright © 2011-2022 走看看