React中的dangerouslySetHTML

出于安全考虑的原因(XSS 攻击),在 React.js 当中所有的表达式插入的内容都会被自动转义,就相当于 jQuery 里面的 text(…) 函数一样,任何的 HTML 格式都会被转义掉:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Editor extends Component {
constructor() {
super()
this.state = {
content: '<h1>组件的dangerouslySetHTML属性</h1>'
}
}

render () {
return (
<div className='editor-wrapper'>
{this.state.content}
</div>
)
}
}

假设上面是一个富文本编辑器组件,富文本编辑器的内容是动态的 HTML 内容,用 this.state.content 来保存。我希望在编辑器内部显示这个动态 HTML 结构,但是因为 React.js 的转义特性,页面上会将待遇作为文字原样显示。

表达式插入并不会把一个

渲染到页面,而是把它的文本形式渲染了。那要怎么才能做到设置动态 HTML 结构的效果呢?React.js 提供了一个属性 dangerouslySetInnerHTML,可以让我们设置动态设置元素的 innerHTML:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Editor extends Component {
constructor() {
super()
this.state = {
content: '<h1>组件的dangerouslySetHTML属性</h1>'
}
}

render () {
return (
<div
className='editor-wrapper'
dangerouslySetInnerHTML={{__html: this.state.content}} />
)
}
}

需要给 dangerouslySetInnerHTML 传入一个对象,这个对象的 __html 属性值就相当于元素的 innerHTML,这样我们就可以动态渲染元素的 innerHTML 结构了。

有写朋友会觉得很奇怪,为什么要把一件这么简单的事情搞得这么复杂,名字又长,还要传入一个奇怪的对象。那是因为设置 innerHTML 可能会导致跨站脚本攻击(XSS),所以 React.js 团队认为把事情搞复杂可以防止(警示)大家滥用这个属性。这个属性不必要的情况就不要使用。