将JSX格式的字符串注入React Component

时间:2017-08-22 11:50:04

标签: javascript html reactjs babeljs

我有一个小的反应页面,应编译并显示html字符串。 用react-foundation

写的字符串中的html

页面如下所示:

import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { Link, Button, Colors } from 'react-foundation';
require('./foundation.css')

var htmlFromApi = '<div className="button-basics-example"><Button color={Colors.SUCCESS}>Save</Button><Button color={Colors.ALERT}>Delete</Button></div>';

var App = ({ html }) => { return <div>{html}</div> }

ReactDOM.render(
<App html={htmlFromApi}/>,
document.getElementById('react')
);

上面代码的结果只是一个字符串,我想知道是否有办法将html字符串转换为反应元素

类似的东西:

var reactElement= toReactElement(htmlFromApi);
//the result is <div className="button-basics-example"><Button color={Colors.SUCCESS}>Save</Button><Button color={Colors.ALERT}>Delete</Button></div>

PS我试过<div className="content" dangerouslySetInnerHTML={{ __html: htmlFromApi }}></div>并且没有工作

提前致谢

编辑:代码为here

2 个答案:

答案 0 :(得分:2)

我最初提供了一个答案,说明如何将字符串作为HTML直接插入到React中。但是,由于您还希望在将字符串中的变量插入到React之前进行解析(以及其他可能的逻辑),因此我在这里留下了两个选项,因为它们可能对将来的读者有用。

案例1 - 您的字符串已准备好插入

如果包含HTML的字符串已准备好直接插入React,并且不包含需要首先解析的代码,则应使用dangerouslySetInnerHTML。您应该在包含div的包装div上设置它。

请参阅下面的示例。

var htmlFromApi = '<div className="button-basics-example"><Button color={Colors.SUCCESS}>Save</Button><Button color={Colors.ALERT}>Delete</Button></div>';

var App = ({html}) => { return <div dangerouslySetInnerHTML={{ __html: html}}></div> }

ReactDOM.render(<App html={htmlFromApi}/>, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.js"></script>
<div id="app"></div>

案例2 - 您的字符串未就绪,在插入之前需要额外的逻辑

如果您的字符串没有“准备好”直接注入DOM,但首先需要某种处理(例如,您的字符串包含需要首先解释的变量),事情变得更加复杂。不幸的是,没有好的或“推荐”的方法来做到这一点。

  • 如果所需的操作简单且相当静态,您可以使用正则表达式。虽然这种方法有限制。此方法的用例可能是操作DOM类或向字符串添加元素。
  • 另一种方法是使用可以帮助您查找所需内容的库,例如html-to-react
  • 最后,如果您使用的是Babel(几乎可以肯定的话),您可以使用Babel变换器。您只需要将babel-core导入代码并将字符串转换为JSX。这种方法可能比使用库更有限,但它应该足够了。

以下是如何从上面实施第3点:

Babel.transform(code, options);

code是你的html字符串。在options中,我们需要传递一个带有{presets: ['react']}的对象,以便Babel理解希望JSX作为输出。你当然可以在这里添加其他选项。

这将返回一个包含source-map等内容的对象,但我们只对这里生成的代码感兴趣。所以我们需要添加:

Babel.transform(code, options).code;

请注意,code是字符串格式的javascript代码,它表示函数调用以创建具有React.createElement的React元素。要在javascript中将字符串作为代码执行,我们可以使用eval()

然后我们可以将这个React元素添加到我们的React组件中并正常渲染它,如下例所示。

var htmlFromApi = '<div className="button-basics-example"><Button color={Colors.SUCCESS}>Save</Button><Button color={Colors.ALERT}>Delete</Button></div>';
var Colors = {SUCCESS: "green", ALERT: "red"};

var App = ({html}) => {
  var Component = Babel.transform(htmlFromApi, {presets: ["react"]}).code;
  return <div>{eval(Component)}</div>;
};

var Button = ({color, children}) => (
  <button style={{backgroundColor: color}}>{children}</button>
);

ReactDOM.render(<App />, document.getElementById("app"));
<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="app"></div>

有关Babel.transform的详细信息,请参阅official documentation

答案 1 :(得分:0)

尝试使用react-string-format npm软件包。 示例:

import { format } from 'react-string-format';
...
format('hiperlink: {0}, span tag: {1}', <a href="#">Click Me</a>, <span>Bla-bla</span>);