React Iframe 使用探索

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

  • 跨域问题
  • Ajax 前进后退问题
  • 异步上传问题
  • 跨框架问题

父页面

基础 React 框架

import React, { PureComponent } from 'react';

export default class Iframe extends PureComponent {

    render () {
        return (
            

Parent

Send Message

Show Message
); } }

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 () {
        ...
    }
}
  • handleParentClick 函数是处理 Hi child 按钮点击事件的:

    1. 先从 DOM 中获得名字为 myFrame 的节点(后文 iframe 部分会展示)。
    2. 通过 contentWindow.postMessage 方法向 iframe 传递信息,参数有两个,第一个是传递的信息内容(This is parent),另一个是 targetOrigin,即目标域,* 表示当前域,也可以写成 http://baidu.com 等其他域名,但注意 iframe 的域必须和这个域名一致。
    3. 后面 2 行通过 contentWindow.document.body.offsetHeight 获得 iframe 页面高度,方便后续做自适应调整,+60 因为样式上会产生其他的高度,这里是作为 buffer,实际使用中根据需要调整。
    4. 后面 3 行通过打印的方式展现常用可以获取的 iframe 信息,包括 window, document, html 等。
  • componentDidMount 函数是在页面加载后执行,React 的典型语法,这里增加了 parent 对 iframe 的事件监听。

    window.addEventListener("message", this.receiveMessageFromIframe, false); 
    

    第一个参数不能修改,事件名称是 message,第二个参数是 eventHandler,这里使用外面定义的 receiveMessageFromIframe 方法,第三个参数是默认值。

  • receiveMessageFromIframe 函数是事件监听的处理函数,注意 React 也会使用 message 数据驱动,所以这里有过滤 message 以 setImmediate 开头的信息,以捕获 iframe 真正传输的数据。获得数据后在展示区 results div 添加获得的信息。

iframe 页面

export default class Iframe extends PureComponent {
    render () {
        return (
             
...