React:如何加载和渲染外部html文件

React: how to load and render external html file?

本文关键字:外部 文件 html 加载 何加载 React      更新时间:2023-09-26

我用React和Redux构建了一个小博客应用程序。这个博客显示了文章的标题、作者、标签和描述。当点击标题或"阅读更多"按钮,我想加载并呈现一个HTML文件与相应的帖子从本地项目的数据文件夹与所有的帖子。

Redux正在管理博客的状态,加载初始帖子。包含8个不同帖子的json文件,包括data文件夹中相应html文件的htmlPath。

我认为你有两个问题需要解决。首先是如何在React中设置元素的innerHTML。另一个是如何根据给定的变量(例如当前路由,文本字段的输入等)获得特定的HTML来渲染。

1。设置元素

innerHTML

您可以使用dangerouslySetInnerHTML道具执行此操作。顾名思义,它将所述元素的innerHTML设置为您指定的任何内容…是的,"危险的"。是准确的,因为它旨在让您在使用此功能之前三思。

官方文档的内容如下:

不当使用innerHTML可能会使您受到跨站点脚本(XSS)攻击。清除用户输入以显示是出了名的容易出错,而未能正确清除是互联网上web漏洞的主要原因之一。

查看这个演示或下面的代码片段。

var Demo = React.createClass({
  getInitialState: function() {
    return {showExternalHTML: false};
  },
  
  render: function() {
    return (
      <div>
        <button onClick={this.toggleExternalHTML}>Toggle Html</button>
        {this.state.showExternalHTML ? <div>
          <div dangerouslySetInnerHTML={this.createMarkup()} ></div>
        </div> : null}
      </div>
    );
  },
  
  toggleExternalHTML: function() {
    this.setState({showExternalHTML: !this.state.showExternalHTML});
  },
  
  createMarkup: function() { 
    return {__html: '<div class="ext">Hello!</div>'};
  }
});
ReactDOM.render(
  <Demo />,
  document.getElementById('container')
);
.ext {
  margin-top: 20px;
  width: 100%;
  height: 100px;
  background: green;
  color: white;
  font-size: 40px;
  text-align: center;
  line-height: 100px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="container"></div>


2。从外部源获取HTML

请注意,上面的示例实际上并没有从外部文件获取HTML,而是直接作为字符串输入。

动态获取选择特定文件的一种简单方法是让后端(例如php)从本地文件夹读取文件,解析文本,并通过AJAX请求将其发送回来。

<标题> 例子
//Your React component
fetchExternalHTML: function(fileName) {
  Ajax.getJSON('/myAPI/getExternalHTML/' + fileName).then(
    response => {
      this.setState({
        extHTML: response
      });
    }, err => {
      //handle your error here
    }
  );
}

虽然Chris的回答很好,但要让它起作用还需要更多的挖掘。以下是您需要采取的步骤:

添加html加载器到你的项目:

npm i -D html-loader

将以下规则添加到你的webpack中。配置文件:

{
  test: /'.(html)$/,
  use: {
    loader: 'html-loader',
    options: {
      attrs: [':data-src']
    }
  }
}

现在你可以导入你的html文件如下:

import React, { Component } from 'react';
import Page from './test.html';
var htmlDoc = {__html: Page};
export default class Doc extends Component {
  constructor(props){
    super(props);
  }
  render(){
     return (<div dangerouslySetInnerHTML={htmlDoc} />)
}}

如果你真的确定,用服务器代码从文件系统中获取你喜欢的前端内容,并在React组件中显示dangerouslySetInnerHTML:

function createMarkup() { 
    return {__html: 'First &middot; Second'}; 
};
<div dangerouslySetInnerHTML={createMarkup()} />

更多文档:https://facebook.github.io/react/tips/dangerously-set-inner-html.html

你可以试试react-templates。这是最好的。你可以把你的模板作为一个外部文件,并可以随时加载它,它会像魅力一样呈现所有可用的React API。

希望能有所帮助。

假设要包含的外部页面在您的应用程序编译时是未知的,并且您不需要应用程序和页面能够交互(例如,页面是一个独立的HTML,例如使用Markdown引擎呈现),iframe HTML元素可以很好地完成这项工作。(详见https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe)。

语法如下:

<iframe src="link/to/your/html/page.html"></iframe>

…瞧,您的页面显示在iframe .

它有一些优点:

  • 它创建了一个新的导航上下文,因此"隔离"了从应用程序的外部页面,使其相对安全的使用时,显示用户提交的内容,至少与直接包含。

和一些缺点:

  • 由于隔离,你的应用程序的CSS不会应用到页面,你必须手动将它包含在页面中。
  • 同样,你不能与应用程序中的页面DOM进行交互。
  • 与直接包含在应用程序中相比,拥有多个导航上下文可能是昂贵的。这对单个页面来说不是问题,但如果你有第100个帖子,你可能必须确保不是所有的外部页面同时显示(例如,make是为了一次只能应用view more)。
  • 页面内的链接不会受到应用程序最终链接解析的影响。这可能会迫使你在链接和路径方面保持两种不同的约定:一个用于应用程序,一个用于页面。