React.js:设置innerHTML 与危险的SetInnerHTML

IT技术 javascript html reactjs innerhtml
2021-03-05 03:57:09

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

例子:

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>
    );
  }
});

我正在做一些比上面的例子更复杂的事情,但总体思路是一样的

5个回答

是,有一点不同!

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

然而,当你使用dangerouslySetInnerHTML时,在幕后让 React 知道该组件内部的 HTML 不是它关心的东西。

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

更重要的是,如果只是简单的使用innerHTML,React 并没有办法知道 DOM 节点被修改了。下次render调用函数时,React 将使用它认为该 DOM 节点的正确状态应该是什么来覆盖手动注入的内容

componentDidUpdate用于始终确保内容同步的解决方案我相信会起作用,但在每次渲染期间可能会出现flash。

我写了一个小的、非科学的性能测试来显示内联 SVG 和使用之间的区别dangerouslySetInnerHTMLwebpackbin.com/bins/-KepHa-AMxQgGxOUnAac - 调出innerHTML方法几乎快两倍(参见webpackbin中的控制台)
2021-04-29 03:57:09
这是真的,而且很容易预测。由于innerHTML 是一种本地方法,它将SVG 代码直接绑定到DOM 而不考虑任何事情。另一方面,危险的SetInnerHTML 是来自React 的方法,SVG 代码必须先解析为React Component 子项,然后才能将它们放入虚拟DOM,然后渲染到DOM。
2021-05-03 03:57:09

可以直接绑定dom

<div dangerouslySetInnerHTML={{__html: '<p>First &middot; Second</p>'}}></div>

根据Dangerously Set innerHTML

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

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

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

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

<div dangerouslySetInnerHTML={createMarkup()} /> 

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

文档React DOM Elements-dangerouslySetInnerHTML

这不能回答问题。
2021-04-23 03:57:09

基于(危险的SetInnerHTML)。

这是一个完全符合您要求的props。然而,他们命名它是为了传达应该谨慎使用它

好吧,根据文档,这似乎是唯一的原因,仍然很困惑
2021-05-03 03:57:09

是的,两者之间存在差异 dangerouslySetInnerHTML::React diffing 算法(https://reactjs.org/docs/reconciliation.html)旨在忽略在此属性下修改的 HTML 节点,从而略微提高性能。如果我们使用 innerHTML,React 无法知道 DOM 被修改了。下一次渲染发生时,React 将覆盖手动注入的内容,它认为该 DOM 节点的正确状态应该是什么。这就是componentDidUpdate拯救的地方