简体   繁体   English

如何将外部 html 文件导入 React 应用程序?

[英]How to import external html file to React app?

I have a project in a middle of development.我有一个正在开发的项目。 And I need to use external landing page as a home page.我需要使用外部登陆页面作为主页。 Therefore, I need to import landings index.html, but it has its own folders with css and js(mainly Jquery code).因此,我需要导入登陆index.html,但它有自己的css和js文件夹(主要是Jquery代码)。

I wanted to import it as <iframe src={html}></iframe> into my project but my app doesn't seem to load htmls.我想将它作为<iframe src={html}></iframe>导入到我的项目中,但我的应用似乎没有加载 html。

What are best ways to import html files that use own jquery code to react?导入使用自己的 jquery 代码做出反应的 html 文件的最佳方法是什么?

This is a bit tricky, and there might be other ways (perhaps better) to achieve the same result.这有点棘手,可能还有其他方法(也许更好)来实现相同的结果。 Also, I would consider the performance impact of loading multiple libraries into an existing React app.另外,我会考虑将多个库加载到现有 React 应用程序中的性能影响。

With that humble disclaimer out of the way, one way to do this would be to include jQuery directly into React's main index.html page using <script> tags, this will make $ globally available across the app:有了这个不起眼的免责声明,一种方法是使用<script>标签将 jQuery 直接包含到 React 的主index.html页面中,这将使$在整个应用程序中全局可用:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <meta
      name="description"
      content="Web site created using create-react-app"
    />
    <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />

    <title>React App</title>

  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>

    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
  </body>
</html>

Once this is done, place the landing page project folder (along with its dependencies) inside the public directory:完成此操作后,将登录页面项目文件夹(及其依赖项)放在public目录中:

项目文件夹布局

Then, from the main app component load the desired landing page using fetch , then use .text() to transform the retrieved page into regular text.然后,使用fetch从主应用程序组件加载所需的登录页面,然后使用.text()将检索到的页面转换为常规文本。

Use setState to set the retrieved HTML into the app state, then inside render() use a regular <div> container to store the landing page and use the React attribute dangerouslySetInnerHTML to set HTML inside that target container.使用setState将检索到的 HTML 设置为应用程序状态,然后在render()中使用常规<div>容器存储登录页面,并使用 React 属性dangerouslySetInnerHTML在目标容器中设置 HTML。

Finally, I pass an anonymous function (as a second parameter to setState ) and use jQuery's getScript() to load and execute the required JS libraries that the landing page depends on.最后,我传递了一个匿名函数(作为setState的第二个参数)并使用 jQuery 的getScript()来加载和执行登录页面所依赖的所需 JS 库。

In the example, I loaded Bootstrap's JS, which is needed to power the Carousel .在示例中,我加载了启动Carousel所需的 Bootstrap 的 JS。

Bootstrap's CSS is loaded directly from the landing page's HTML file using a standard <link> tag. Bootstrap 的 CSS 是使用标准<link>标签直接从登录页面的 HTML 文件加载的。

import React from "react";

class App extends React.Component {
  state = {
    page: null
  };

  componentDidMount() {
    fetch("landing-page-one/index.html")
      .then(result => {
        return result.text();
      })
      .then(page => {
        this.setState(
          {
            page: { __html: page }
          },
          () => {
            window.$.getScript("landing-page-one/js/index.js");
          }
        );
      });
  }

  render() {
    const { page } = this.state;
    return (
      <>
        <h2>
          <span>Inserting project using React's </span>
          <code>dangerouslySetInnerHTML</code>:
        </h2>
        <div
          dangerouslySetInnerHTML={page && page}
        />
      </>
    );
  }
}

export default App;

Working example here . 这里的工作示例。

I was also trying to find out a solution and figured out two ways for different use cases:我也试图找到一个解决方案,并为不同的用例找到了两种方法:

  1. If your HTML file contains <div> and other child tags (that can be nested under other <div> or <body> tags) then this approach will work for you:如果您的 HTML 文件包含 <div> 和其他子标签(可以嵌套在其他 <div> 或 <body> 标签下),那么这种方法将适用于您:

Example with Method 1:方法 1 的示例:

    const parse = require("html-react-parser");
    const docs = require("../../public/redoc-static.html").default;
    
    const ApiDocs = (props: any) => {    
      return (
        <Box sx={{ display: "flex", height: "100vh" }}>
            <Box>{parse(docs)}</Box>
          </Box>
      );
    };

  1. If your HTML file contains a <html> tag (is a complete file) following the above approach would give the very obvious error <html> cannot appear as a child of <div> .如果您的 HTML 文件包含 <html> 标记(是一个完整的文件),则按照上述方法会给出非常明显的错误<html> cannot appear as a child of <div> In that case, the workaround I found is to open the whole HTML file in a different tab of the browser with _blank :在这种情况下,我发现的解决方法是使用_blank在浏览器的不同选项卡中打开整个 HTML 文件:

Example with Method 2:方法 2 的示例:

window.open(filename, "_blank")

Note: The HTML file has to reside in the public folder of your project.注意:HTML 文件必须位于项目的公共文件夹中。

I'm just going to through this out there as a spitball... I've never tried it, but why not directly replace index.html and not render anything on that page?我只是把它当作一个吐球来解决......我从未尝试过,但为什么不直接替换 index.html 并且不在该页面上呈现任何内容呢? You would have to either adjust the build somehow... I have no idea how to, or manually put it after the react app finishes building.您将不得不以某种方式调整构建......我不知道如何,或者在反应应用程序完成构建后手动放置它。 I'm sure it would be a bug nightmare, but it honestly sounds a little less of a hastle than an iframe which might give you some weird UI behavior.我敢肯定这将是一个错误的噩梦,但老实说,它听起来不像 iframe 那样麻烦,它可能会给你一些奇怪的 UI 行为。 React-Server, even though it says server, really just takes stringified JSX and I think html translates it back to workable code. React-Server,尽管它说的是服务器,但实际上只需要字符串化的 JSX,我认为html 会将其转换回可行的代码。 You could also try that approach, but this does sound like a nightmare project.您也可以尝试这种方法,但这听起来确实像一个噩梦项目。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM