React Iframe 使用探索

2019-09-16  本文已影响0人  Sisyphus235

作者后端经验比较丰富,近期要做跨域跨前端框架的前端页面展示,自然联想到了 IFRAME 方法,细致了解下来发现它可以用来解决很多棘手问题,包括:

父页面

基础 React 框架

import React, { PureComponent } from 'react';

export default class Iframe extends PureComponent {

    render () {
        return (
            <div>
                <h1>Parent</h1>
                <p>Send Message 
                    <button id="message_button" onClick={this.handleParentClick.bind(this)}>Hi child</button>
                </p>
                <span> Show Message </span>
                <div id='results'></div>
            </div>
        );
    }
}

importexport 外部都是 React 基本框架,内部显示了页面布局:

Parent
Parent 提示当前部分是父页面;
Send MessageHi child 按钮用来向 iframe 传递消息,按钮绑定了点击事件 handleParentClick,后文会定义;
Show Messageresults div 用来展示 iframe 传来的消息,后文会做处理。

iframe 相关事件

export default class Iframe extends PureComponent {

    receiveMessageFromIframe ( event ) {
        // React will send message started with setImmediate
        if (!event.data.startsWith('setImmediate')){  
          console.log("parent received", event.data);
          const results = document.getElementById('results');
          results.innerHTML = event.data;
        }
    }

    componentDidMount () {
         // "message" name cannot be changed
        window.addEventListener("message", this.receiveMessageFromIframe, false); 
    }

    handleParentClick = () => {
        //必须是iframe加载完成后才可以向子域发送数据
        const childFrameObj = document.getElementById('myFrame');
        childFrameObj.contentWindow.postMessage("This is parent", '*');
        console.log("iframe height", childFrameObj.contentWindow.document.body.offsetHeight);
        childFrameObj.height = childFrameObj.contentWindow.document.body.offsetHeight + 60;  // there will be some margin and stylistic height
        console.log("iframe window", childFrameObj.contentWindow);
        console.log("iframde document", childFrameObj.contentWindow.document);
        console.log("iframe html", childFrameObj.contentWindow.document.documentElement);
    }
    
    render () {
        ...
    }
}

iframe 页面

export default class Iframe extends PureComponent {
    render () {
        return (
             <div>
                ...
                <iframe
                  id="myFrame"
                  width="100%"
                  height={0}
                  frameBorder={1}
                  scrolling="no"
                  srcDoc="
                  <h1>myFrame</h1>
                  <p>Send Message: <button id='message_button'}>Hi parent</button></p>
                  <span>Show Message</span>
                  <div id='results'></div>
                  <script>
                      function receiveMessageFromParent ( event ) {
                        let results = document.getElementById('results');
                        results.innerHTML += event.data + '<br>';
                      };
                      window.addEventListener('message', receiveMessageFromParent, false);
        
                      let messageButton = document.getElementById('message_button');
                      /* console.log('msg button', messageButton); annoataion cannot use \/\/  */
                      messageButton.addEventListener('click', function (e) {
                        console.log('iframe send msg');
                        console.log('parent', window.parent);
                        console.log('top container', window.top);
                        window.parent.postMessage('This is child', '*');
                      }, false);
                  </script>
                  "
                />
             </div>
        );
    }
}

原生 html 页面

id 是 DOM 上节点名称,上文有使用这里的 myFrame 来获得节点进行操作;
width="100%" 是 iframe 宽度,可以是百分比或者数值,百分比可以自适应页面;
frameBorder={1} 是 iframe 边框是否展示,1 代表展示,0 代表不展示;
scrolling="no" 是滚动设置,yes 代表展示,no 代表不展示,auto 代表自动识别;
height={0} 是 iframe 高度,可以是百分比或者数值,这里设置为 0 代表无内容不展示,有内容后上文根据内容高度自适应展示;
srcDoc=<string> 是 iframe 的 DOM,可以使用原生 HTML 编写;
src 是 iframe 的信息源。
srcDoc 内设置了 iframe 页面:

  1. myFrame 提示当前是 iframe 页面;
  2. Send MessageHi parent 是信息传输部分;
  3. Show Messageresults 用来展示从 parent 接受到的信息。

js 控制脚本

整体代码和效果

import React, { PureComponent } from 'react';

export default class Iframe extends PureComponent {

  receiveMessageFromIframe ( event ) {
    if (!event.data.startsWith('setImmediate')){  // React will send message started with setImmediate
      console.log("parent received", event.data);
      const results = document.getElementById('results');
      results.innerHTML = event.data;
    }
  }

  componentDidMount () {
    window.addEventListener("message", this.receiveMessageFromIframe, false);  // "message" name cannot be changed
  }

  handleParentClick = () => {
    //必须是iframe加载完成后才可以向子域发送数据
    const childFrameObj = document.getElementById('myFrame');
    childFrameObj.contentWindow.postMessage("This is parent", '*');
    console.log("iframe height", childFrameObj.contentWindow.document.body.offsetHeight);
    childFrameObj.height = childFrameObj.contentWindow.document.body.offsetHeight + 60;  // there will be some margin and stylistic height
    console.log("iframe window", childFrameObj.contentWindow);
    console.log("iframde document", childFrameObj.contentWindow.document);
    console.log("iframe html", childFrameObj.contentWindow.document.documentElement);
  }

  render () {
    

    return (
      <div>
        <h1>Parent</h1>
        <p>Send Message <button id="message_button" onClick={this.handleParentClick.bind(this)}>Hi child</button></p>
        <span>Show Message </span>
        <div id='results'></div>
        <iframe
          id="myFrame"
          width="100%"
          height={0}
          frameBorder={1}
          scrolling="no"
          srcDoc="
          <h1>myFrame</h1>
          <p>Send Message: <button id='message_button'}>Hi parent</button></p>
          <span>Show Message</span>
          <div id='results'></div>
          <script>
              function receiveMessageFromParent ( event ) {
                let results = document.getElementById('results');
                results.innerHTML += event.data + '<br>';
              };
              window.addEventListener('message', receiveMessageFromParent, false);

              let messageButton = document.getElementById('message_button');
              /* console.log('msg button', messageButton); annoataion cannot use \/\/  */
              messageButton.addEventListener('click', function (e) {
                console.log('iframe send msg');
                console.log('parent', window.parent);
                console.log('top container', window.top);
                window.parent.postMessage('This is child', '*');
              }, false);
          </script>
          "
        />
      </div>
    );
  }
}

上一篇 下一篇

猜你喜欢

热点阅读