【问题标题】:React.js: Set innerHTML vs dangerouslySetInnerHTMLReact.js:设置 innerHTML 与危险地SetInnerHTML
【发布时间】:2016-09-17 03:56:22
【问题描述】:

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

例子:

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

我做的事情比上面的例子稍微复杂一点,但总体思路是一样的

【问题讨论】:

    标签: javascript html reactjs innerhtml


    【解决方案1】:

    是的,有区别!

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

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

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

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

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

    【讨论】:

    • 我写了一个小型的、非科学的性能测试来显示内联 SVG 和使用 dangerouslySetInnerHTML 之间的区别:webpackbin.com/bins/-KepHa-AMxQgGxOUnAac - 调出 innerHTML 方法的速度几乎是原来的两倍(请参阅控制台webpackbin)
    • 这是真的,而且很容易预测。因为innerHTML 是一种将SVG 代码直接绑定到DOM 而不考虑任何事情的本机方法。另一方面,dangerousSetInnerHTML 是来自 React 的方法,它必须将 SVG 代码解析为 React 组件子项,然后才能将它们放入虚拟 DOM,然后渲染到 DOM。
    【解决方案2】:

    可以直接绑定到dom

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

    【讨论】:

      【解决方案3】:

      根据Dangerously Set innerHTML

      innerHTML 的不当使用可以让您打开cross-site scripting (XSS) 攻击。众所周知,清理用户输入以进行显示很容易出错, 未能正确消毒是导致网络问题的主要原因之一 互联网上的漏洞。

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

      在充分了解安全后果并正确 清理数据,创建一个只包含键的新对象 __html 和您的净化数据作为值。这是一个例子 使用 JSX 语法:

      function createMarkup() {
          return {
             __html: 'First &middot; Second'    };
       }; 
      
      <div dangerouslySetInnerHTML={createMarkup()} /> 
      

      使用以下链接了解更多信息:

      文档React DOM Elements - dangerouslySetInnerHTML

      【讨论】:

      • 这不能回答问题。
      【解决方案4】:

      基于 (dangerouslySetInnerHTML)。

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

      【讨论】:

      • 根据文档看来这是唯一的原因,仍然很困惑
      【解决方案5】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-07-24
        • 2019-04-26
        • 2018-04-30
        • 2021-01-23
        • 2020-11-13
        • 2021-01-19
        • 2021-12-11
        • 1970-01-01
        相关资源
        最近更新 更多