关于javascript:在React组件中将HTML字符串呈现为真实HTML

Render HTML string as real HTML in a React component

这是我尝试过的方法以及出现问题的方法。

这有效:

1
Hi there!" }} />

这不是:

1
 

description属性只是HTML内容的普通字符串。 但是由于某种原因,它呈现为字符串,而不是HTML。

enter image description here

有什么建议么?


this.props.match.description是字符串还是对象?如果是字符串,则应将其转换为HTML。例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class App extends React.Component {

constructor() {
    super();
    this.state = {
      description: '<h1 style="color:red;">something'
    }
  }

  render() {
    return (
     
    );
  }
}

ReactDOM.render(<App />, document.getElementById('root'));

结果:http://codepen.io/ilanus/pen/QKgoLA?editors=1011

但是,如果description:

something不带引号'',您将得到:

1
2
3
4
5
6
7
8
9
10
11
?Object {
$$typeof: [object Symbol] {},
  _owner: null,
  key: null,
  props: Object {
    children:"something",
    style:"color:red;"
  },
  ref: null,
  type:"h1"
}

如果它是字符串,并且您没有看到任何HTML标记,那么我看到的唯一问题是标记错误。

更新

如果您正在处理HTMLEntitles。您需要先解码它们,然后再将它们发送到dangerouslySetInnerHTML,这就是为什么他们危险地称呼它:)

工作示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class App extends React.Component {

  constructor() {
    super();
    this.state = {
      description: '<p>
Our Opportunity:
</p>'

    }
  }

   htmlDecode(input){
    var e = document.createElement('div');
    e.innerHTML = input;
    return e.childNodes.length === 0 ?"" : e.childNodes[0].nodeValue;
  }

  render() {
    return (
     
    );
  }
}

ReactDOM.render(<App />, document.getElementById('root'));


我用了'react-html-parser'

1
yarn add react-html-parser
1
2
3
import ReactHtmlParser from 'react-html-parser';

 { ReactHtmlParser (html_string) }

源于npmjs.com

提升@okram的评论以提高知名度:

from its github description: Converts HTML strings directly into React
components avoiding the need to use dangerouslySetInnerHTML from
npmjs.com A utility for converting HTML strings into React components.
Avoids the use of dangerouslySetInnerHTML and converts standard HTML
elements, attributes and inline styles into their React equivalents.


检查您尝试追加到节点的文本是否没有被转义,如下所示:

1
2
3
4
5
var prop = {
    match: {
        description: 'Hi there!'
    }
};

代替这个:

1
2
3
4
5
var prop = {
    match: {
        description: 'Hi there!'
    }
};

如果转义,则应从服务器端进行转换。

The node is text because is escaped

该节点是文本,因为已转义

The node is a dom node because isnt escaped

该节点是dom节点,因为没有转义


如果您可以控制包含html的字符串的来源(即,应用程序中的某个位置),则可以从新的 API中受益,方法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import React, {Fragment} from 'react'

const stringsSomeWithHtml = {
  testOne: (
    <Fragment>
      Some text wrapped with strong
    </Fragment>
  ),
  testTwo: `This is just a plain string, but it'll print fine too`,
}

...

render() {
  return {stringsSomeWithHtml[prop.key]}
}


危险地设置内部HTML

angerouslySetInnerHTML是React在浏览器DOM中使用innerHTML的替代品。通常,通过代码设置HTML是有风险的,因为很容易在无意间使用户遭受跨站点脚本(XSS)攻击。因此,您可以直接从React设置HTML,但是您必须输入angerousedSetInnerHTML并使用__html键传递对象,以提醒自己这很危险。例如:

1
2
3
4
5
6
7
function createMarkup() {
  return {__html: 'First  Second'};
}

function MyComponent() {
  return ;
}

您只使用React的危险的SetInnerHTML方法

或者,您可以通过这种简单的方法实现更多功能:在React应用中渲染HTML原始文件


就我而言,我使用react-render-html

首先通过npm i --save react-render-html安装软件包

然后,

1
2
3
import renderHTML from 'react-render-html';

renderHTML("GitHub")

我无法使npm buildreact-html-parser一起使用。但是,就我而言,我能够成功使用https://reactjs.org/docs/fragments.html。我要求显示一些html unicode字符,但是它们不应该直接嵌入JSX中。在JSX中,必须从组件的状态中选择它。组件代码段如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
constructor()
{
this.state = {
      rankMap : {"5" : <Fragment>&#9733; &#9733; &#9733; &#9733; &#9733;</Fragment> ,
                "4" : <Fragment>&#9733; &#9733; &#9733; &#9733; &#9734;</Fragment>,
                "3" : <Fragment>&#9733; &#9733; &#9733; &#9734; &#9734;</Fragment> ,
                "2" : <Fragment>&#9733; &#9733; &#9734; &#9734; &#9734;</Fragment>,
                "1" : <Fragment>&#9733; &#9734; &#9734; &#9734; &#9734;</Fragment>}
                };
}

render()
{
       return (
                    <small class="text-muted">{ this.state.rankMap["5"] }</small>
               );
}

如果您可以控制{this.props.match.description}并且使用的是JSX。我建议不要使用" dangerouslySetInnerHTML"。

1
2
3
4
5
6
7
// In JSX, you can define a html object rather than a string to contain raw HTML
let description = Hi there!;

// Here is how you print
return (
    {description}
);