跨域库herryPostMessage.js的一些优化,多iframe跨域

之前简单封装过一个旧版,主要是开发chrome插件时使用的。

旧库见文章:https://www.cnblogs.com/wuhairui/p/14595893.html

 

新版库主要做了下多个iframe和父页面交互的优化。主要使用构造函数的方式将多个iframe的交互使用多个对象进行区分,这样多个交互就可以互相独立了。

并可子页面主动调用传值给父页面。

新版代码:

/**
 * iframeId iframe的id
 * parentName 父窗口名,一般不改
 * childName 子窗口名 多个iframe时需要使用
 * postMessage 父窗口调用 需要子页面加载完成后才能执行到
 * returnData 子窗口主动回应
 * callback 父窗口调用后子窗口判断
 */
(function (w) {
  function HerryPostMessage(iframeId = 'iframe') {
    this.iframeId = iframeId;
    this.parentName = '父窗口';
    this.childName = '子窗口';
    //跨域对象
    this.messageObj = {};

    /**
     * 监听父页面发送的数据
     */
    w.addEventListener(
      "message",
      async (event) => {
        const { data } = event;
        if (data && typeof data === "object" && data.name === this.parentName) {
          if (this.callback) {
            this.callback(data)
          }
        }
      },
      false
    );

    /**
     * 监听子页面返回的数据
     */
    w.addEventListener(
      "message",
      (event) => {
        const { data } = event;
        if (data && typeof data === "object" && data.name === this.childName) {
          if(this.messageObj[data.action]) {
            this.messageObj[data.action](data);
          }
        }
      },
      false
    );
  }

  //父页面
  /**
   * 发送给子页面数据
   */
  HerryPostMessage.prototype.postMessage = function(data, fn = null) {
    const iframe = document.getElementById(this.iframeId)
    iframe.contentWindow.postMessage(
      {
        name: this.parentName, //父页面名字
        ...data,
      },
      "*"
    );
    this.messageObj[data.action] = fn;
  };

  //子页面
  /**
   * 返回数据给父页面 参1=当前action 参2=返回的数据
   */
  HerryPostMessage.prototype.returnData = function(action, data) {
    top.postMessage(
      {
        name: this.childName, //子页面名字
        action,
        data,
      },
      "*"
    );
  };

  //抛出
  w.HerryPostMessage = HerryPostMessage;
})(window);

 

使用方法:

父子页面均引入herryPostMessage.js。

父页面:

引入子页面b1,设置一个id

<iframe id="b1" src="//localhost:8081/b1.html" frameborder="0"></iframe>

创建对象,参数传参为iframe的id,设置对象的childName也同名。

父子页面均加载后,调用对象的postMessage方法,传入action,data可传可不传。第二个参数为子页面的回调。

const b1 = new HerryPostMessage('b1')
b1.childName = 'b1';
//此处需要延迟 因为到登录子页面加载完毕
setTimeout(() => {
    b1.postMessage({action:'geta',data: '父页面传给子页面的数据'},(res) => {
        console.log('父页面打印',res.data)
    })
},500)

子页面:

创建该页面的对象(一般和父页面创建的同名)

创建callback函数,做判断,父页面调用后,会进入到这里。处理后可以使用对象的returnData方法将数据传回给父页面的回调函数中。

const b1 = new HerryPostMessage('b1');
b1.childName = 'b1';
b1.callback = (data) => {
    if(data.action === 'geta') {
        //获取到父页面传来的数据
        console.log('子页面打印',data.data)
        //子页面回传给父页面数据
        b1.returnData('geta','子页面回传给父页面数据')
    }
}

另外,在子页面中直接调用returnData也可以主动传回给父页面数据

setTimeout(() => {
    b1.returnData('geta','子页面主动传给父页面数据')
},1000)

效果:

 

posted @ 2021-04-15 22:21  herry菌  阅读(324)  评论(0编辑  收藏  举报