zoukankan      html  css  js  c++  java
  • 跨域库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)

    效果:

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

  • 相关阅读:
    MySQL
    Shell运算符:Shell算数运算符、关系运算符、布尔运算符、字符串运算符等
    ps
    top
    sed
    nav响应范围一定要足够宽
    续上获取input的checked用prop时返回的是布尔值
    jq不应该用attr获取input的check值
    jq祖级元素
    一些jquery的坑
  • 原文地址:https://www.cnblogs.com/wuhairui/p/14664750.html
Copyright © 2011-2022 走看看