React.js:设置innerHTML与dangerouslySetInnerHTML

Jsh*_*523 135 html javascript reactjs

设置元素的innerHTML与在元素上设置dangerouslySetInnerHTML属性有什么"幕后"的区别吗?假设我为了简单起见正确地清理了东西.

例:

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

VS

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

我做的事情比上面的例子复杂一点,但总的想法是一样的

小智 184

是,有一点不同!

使用innerHTMLvs 的直接影响dangerouslySetInnerHTML是相同的 - DOM节点将使用注入的HTML进行更新.

但是,在您使用dangerouslySetInnerHTML它的幕后,让React知道该组件内部的HTML不是它关心的东西.

因为React使用虚拟DOM,当它将diff与实际DOM进行比较时,它可以直接绕过检查该节点的子节点,因为它知道HTML来自另一个源.所以性能提升了.

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

您使用的解决方案componentDidUpdate始终确保内容是同步的,我相信它会起作用,但每次渲染时可能会有闪光.

  • 我写了一个小的,非科学的性能测试,以显示内联SVG和使用`dangerouslySetInnerHTML`之间的区别:https://www.webpackbin.com/bins/-KepHa-AMxQgGxOUnAac - 调整innerHTML方法几乎是两倍快(请参阅webpackbin中的控制台) (9认同)
  • 这是真实的,很容易预测。由于innerHTML是一种本地方法,无需考虑任何因素即可直接将SVG代码绑定到DOM。另一方面,angerousedSetInnerHTML是来自React的方法,必须先将SVG代码解析为React Component子元素,然后才能将它们放入虚拟DOM中,然后呈现给DOM。 (2认同)

小智 14

根据Dangerously Set innerHTML

不当使用innerHTML可能会导致跨站点脚本 (XSS) 攻击。众所周知,清理用于显示的用户输入容易出错,而未能正确清理是 Internet 上 Web 漏洞的主要原因之一。

我们的设计理念是让事情变得安全应该“容易”,开发人员在执行“不安全”操作时应该明确说明他们的意图。道具名称dangerouslySetInnerHTML被故意选择为令人恐惧,道具值(一个对象而不是字符串)可用于指示已清理的数据。

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

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

<div dangerouslySetInnerHTML={createMarkup()} /> 
Run Code Online (Sandbox Code Playgroud)

使用以下链接阅读更多信息:

文档React DOM Elements-dangerouslySetInnerHTML

  • 这并不能回答问题。 (5认同)

Lek*_*ens 13

可以直接绑定dom

<div dangerouslySetInnerHTML={{__html: '<p>First &middot; Second</p>'}}></div>
Run Code Online (Sandbox Code Playgroud)