React.js:设置innerHTML vs危险地设置InnerHTML


171

在元素上设置元素的innerHTML与在元素上设置危险地设置InnerHTML属性有什么“幕后”区别?假设为简单起见,我正在对事物进行适当的消毒。

例:

var test = React.createClass({
  render: function(){
    return (
      <div contentEditable='true' dangerouslySetInnerHTML={{ __html: "Hello" }}></div>
    );
  }
});

var test = React.createClass({
  componentDidUpdate: function(prevProp, prevState){
    this.refs.test.innerHTML = "Hello";
  },
  render: function(){
    return (
      <div contentEditable='true' ref='test'></div>
    );
  }
});

我做的事情比上面的示例复杂一些,但总体思路是相同的

Answers:


236

是,有一点不同!

使用innerHTMLvs 的直接效果dangerouslySetInnerHTML是相同的-DOM节点将使用注入的HTML更新。

但是,在使用dangerouslySetInnerHTML它时,让React 在幕后知道该组件内部的HTML并不是它关心的。

由于React使用了虚拟DOM,因此在比较diff与实际DOM时,它可以直接跳过该节点的子节点,因为它知道HTML来自其他来源。这样就可以提高性能。

更重要的是,如果仅使用innerHTML,React无法知道DOM节点已被修改。下次render调用该函数时,React将用它认为该DOM节点的正确状态应覆盖的内容覆盖手动注入的内容

componentDidUpdate我认为可以始终确保内容同步的解决方案,我相信它可以工作,但是在每次渲染过程中可能会有闪光。


11
我写了一个小型的非科学的性能测试,以显示内联SVG和使用dangerouslySetInnerHTML以下代码之间的区别:webpackbin.com/bins/-KepHa-AMxQgGxOUnAac-调出innerHTML方法的速度几乎快一倍(请参阅webpackbin中的控制台)
Joscha

4
这是真实且容易预测的。由于innerHTML是一种本地方法,无需考虑任何因素即可将SVG代码直接绑定到DOM。另一方面,angerousedSetInnerHTML是来自React的方法,必须先将SVG代码解析为React Component子元素,然后才能将它们放入虚拟DOM中,然后呈现给DOM。
Up209d

3

根据危险设置innerHTML

使用不当innerHTML可能会使您面临跨站点脚本(XSS) 攻击。众所周知,对用户输入进行显示处理很容易出错,并且无法正确进行清理是互联网上网络漏洞的主要原因之一。

我们的设计理念是确保事物安全应该“容易”,开发人员在执行“不安全”操作时应明确声明其意图。dangerouslySetInnerHTML故意将prop名称选择为吓人的,并且prop值(对象而不是字符串)可用于指示已清理的数据。

充分了解安全性后果并正确清除数据后,创建一个仅包含密钥__html和已清除数据作为值的新对象 。这是使用JSX语法的示例:

function createMarkup() {
    return {
       __html: 'First &middot; Second'    };
 }; 

<div dangerouslySetInnerHTML={createMarkup()} /> 

使用以下链接阅读有关它的更多信息:

文档React DOM元素-hazardlySetInnerHTML


1
这不能回答问题。
昆汀

2

基于(危险地为SetInnerHTML)。

这是一款完全可以满足您需求的道具。但是,它们的名称表示要谨慎使用


1
根据文档以及看来这是唯一的原因,仍然感到困惑
mkb
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.