【问题标题】:Inject JSX-formatted string into React Component将 JSX 格式的字符串注入 React 组件
【发布时间】:2018-01-30 16:37:21
【问题描述】:

我有一个小的反应页面,应该编译和显示 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')
);

上面代码的Result只是一个字符串,我想知道有没有办法将html字符串转换为react元素

类似这样的:

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 我试过&lt;div className="content" dangerouslySetInnerHTML={{ __html: htmlFromApi }}&gt;&lt;/div&gt; 还是不行

提前致谢

编辑:代码是here

【问题讨论】:

  • 尝试使用 dangerouslySetInnerHTML - facebook.github.io/react/docs/…
  • React.createElement(elementString, propsObject) 怎么样?
  • @Dan 没用,bcz dangerouslySetInnerHTML 期望编译的 html 字符串,但我的字符串没有编译
  • @isa424 我不能使用 React.createElement bcz 我不知道字符串会是什么样子,而且它是一个很长的字符串,有很多嵌套组件

标签: javascript html reactjs babeljs


【解决方案1】:

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


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

如果包含 HTML 的字符串可以直接插入到 React 中,并且不包含需要首先解析的代码,则应该使用 dangerouslySetInnerHTML。您应该在包含从您的 API 获取的 HTML 的包装 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 作为我们的输出。当然,您也可以在此处添加其他选项。

这将返回一个包含源映射等内容的对象,但我们只对此处生成的代码感兴趣。所以我们需要添加:

Babel.transform(code, options).code;

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

然后我们可以将这个 React Element 添加到我们的 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

【讨论】:

  • 感谢您的回答,但是这样字符串中的值将不会被评估或编译,对吗,对不起,我的反应很差
  • 这是使用 css 后的结果codepen.io/anon/pen/oeddYN?editors=1111
  • 只是一个简短的说明,但我认为您不想在外部 div 中包含 className,因为它不能正确输出。它在浏览器中以 classname="button-basics-example" 的属性结束。仅使用单词 class,然后在笔内的 css 中为 button-basic-example 设置一些样式,我能够产生一些样式,但当它在 html 字符串中使用 className 时则不行。对此有什么想法吗?
  • @DanielZuzevich dangerouslySetInnerHTML 期望编译后的 html,所以没有办法让它编译包含像 这样的组件的字符串,而我拥有的字符串是未编译的 html ,所以我需要一个编译 html 然后将其传递给 dangerouslySetInnerHTML 的方法
  • @Rana,我已经更新了我的答案。请看一看。
【解决方案2】:

尝试使用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>); 

【讨论】:

    猜你喜欢
    • 2021-08-24
    • 2020-07-10
    • 2021-01-19
    • 2015-06-01
    • 2018-12-30
    • 1970-01-01
    • 2019-01-03
    • 1970-01-01
    • 2016-09-16
    相关资源
    最近更新 更多