天天看點

react元件中通過iframe嵌入html頁面

最近在一個web前端開發的項目中,遇到了這樣一個需求:項目本身使用react搭建,用antd來完成各種元件的展示,有一個需求,是要将另外一個項目中的部分頁面功能加進來,另外的一個項目使用的是bootstrap+ajax庫寫的純html頁面。

最直接的方法,将這些要加進來的頁面功能使用react元件重寫一遍,加到項目中,但是這樣做成本非常高。于是想有沒有方法,将這些html頁面直接以連接配接的方式嵌入到現有react元件中展示。google了一下,可以通過ifram來完成。

現有的react項目使用的是【上中下】布局,點選header中的menu會觸發路由,渲染不同的react元件在content中顯示。如下:

react元件中通過iframe嵌入html頁面

改造的思路是:寫一個帶有ifram的react元件(HtmlPage.js),點選對應的menus,傳入不同的參數到對應的路由,路由會渲染該元件,同時元件會接受一個參數,用來給ifram指定不同的頁面url路徑。具體代碼如下:

1、HtmlPage.js元件代碼:

import React, { Component } from 'react';

var root_path = "http://abc.edf/test/";

export default class HtmlPage extends Component {
    constructor(props) {
        super(props);
        this.state = {
            iFrameHeight: '0px'
        }
    }
    render() {
        let path = this.props.match.params.path;//路由參數
        let url = root_path+"default.html";
        if (path === "service") {
            url = root_path+"service.html";
        } else if (path === "interfaceCase") {
            url = root_path+"interface_view.html";
        } 
        console.log(path,url);
        return (
            <div>
                <iframe  ref="iframe" scrolling="yes" frameBorder="0"
                    style={{width:'100%',height:this.state.iFrameHeight, overflow:'visible'}}
                    onLoad={() => {//iframe高度不超過content的高度即可
                        let h = document.documentElement.clientHeight - 20;
                        this.setState({
                            "iFrameHeight": h + 'px'
                        });
                    }} 
                    src={url}
                />
            </div>
        )
    }
}      

這個元件中使用了iframe,并且根據參數來設定iframe的src。此外,元件還根據不同ifram src頁面的高度,動态設定了ifram的height屬性。

參考:​​https://www.jianshu.com/p/a288aa0f73fa​​

2、主架構代碼App.js:

function App() {
    return (
      <div >
        <Layout style={{ height:"100%" }}>
          <HashRouter>
            <Header style={{ height: "48px", padding: "0 10px", position: 'fixed', zIndex: 9, width: '100%' }}>
              <HeaderNav/>
            </Header>
            <Content style={{ backgroundColor: 'white', marginTop: '48px',minHeight: document.documentElement.clientHeight - restHeight }}>
                <Switch>
                  <Route exact path="/home" component={Home} />
                  <Route path="/htmlPage/:path"component={HtmlPage} />
                  <Route path="/caseManage" component={JEditorComponent} />
                  <Route path="/other" render={() => <h1>未完待續。。。</h1>} />
                  <Redirect to="/home"/>
                </Switch>  
            </Content>
            <Footer style={{ height: "20px", padding: '0px', textAlign: 'center', color: 'rgba(0,0,0,0.5)' }}>
              Copyright © 2020 abc Limited All Rights Reserved.
            </Footer>
          </HashRouter>
        </Layout>
      </div>
    );
  }      

這裡設定了一個路由“/htmlPage/:path”,當menu路由到這個規則上,就會渲染上面的HtmlPage.js元件,同時傳遞一個path參數,用來指定iframe的url連接配接位址,這個位址就可以是另外一個項目的html頁面。

import React, { Component } from 'react'
import { Link } from 'react-router-dom'
import { Menu, Icon } from 'antd';
import "./HeaderNav.css";

const { SubMenu } = Menu;

export default class HeaderNav extends Component {
    
    render() {
        return (
            <div className="header-nav">
                <Menu  mode="horizontal" theme="dark" defaultSelectedKeys={['home']}>
                    <Menu.Item key="home">
                        <Link to="/home">
                            <Icon type="home" />
                            Home
                        </Link>
                    </Menu.Item>
                    <SubMenu
                        title={
                            <span className="submenu-title-wrapper">
                                <Icon type="setting" />
                                Meta data 
                            </span>
                        }
                    >
                        <Menu.Item key="service_manage">
                            <Link to="/htmlPage/service">
                                service manage
                            </Link>
                        </Menu.Item>
                        <Menu.Item key="interface_manage">
                            <Link to="/htmlPage/interfaceCase">
                                interface manage
                            </Link>
                        </Menu.Item>
                        <Menu.Item key="case_manage">
                            <Link to="/caseManage">
                                case manage
                            </Link>
                        </Menu.Item>
                    </SubMenu>
                </Menu>
            </div>
        )
    }
}