设置元素的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>
);
}
});
我正在做一些比上面的例子复杂一点的事情,但总体思路是一样的
是的,有区别!
使用
innerHTML
与 dangerouslySetInnerHTML
的直接效果是相同的——DOM 节点将使用注入的 HTML 进行更新。
但是,当你在幕后使用
dangerouslySetInnerHTML
时,它会让React知道该组件内部的HTML不是它关心的东西。
因为 React 使用虚拟 DOM,所以当它与实际 DOM 进行比较时,它可以直接绕过检查该节点的子节点因为它知道 HTML 来自另一个源。因此,性能有所提升。
更重要的是,如果你简单地使用
innerHTML
,React没有办法知道DOM节点已经被修改了。下次调用 render
函数时,React 将覆盖手动注入的内容,它认为 DOM 节点的正确状态应该是这样的。
您使用
componentDidUpdate
始终确保内容同步的解决方案我相信会起作用,但每次渲染期间可能会出现闪烁。
可以直接绑定dom
<div dangerouslySetInnerHTML={{__html: '<p>First · Second</p>'}}></div>
不当使用
可能会导致 跨站点 脚本(XSS) 攻击。众所周知,清理用户输入以进行显示很容易出错, 未能正确消毒是网络问题的主要原因之一 互联网上的漏洞。innerHTML
我们的设计理念是让事情变得安全应该“容易”, 开发人员在执行时应明确说明其意图 “不安全”操作。道具名称
是 故意选择令人恐惧的,并且 prop 值(一个对象 而不是字符串)可用于指示已清理的数据。dangerouslySetInnerHTML
在充分了解安全后果并正确处理后 清理数据,创建一个仅包含密钥的新对象
并将您清理后的数据作为值。这是一个例子 使用 JSX 语法:__html
function createMarkup() {
return {
__html: 'First · Second' };
};
<div dangerouslySetInnerHTML={createMarkup()} />
使用以下链接了解更多信息:
是的,两者之间存在差异:
dangerouslySetInnerHTML
:React diffing 算法(https://reactjs.org/docs/reconciliation.html)旨在忽略此属性下修改的 HTML 节点,从而稍微提高性能。
如果我们使用innerHTML
,React 无法知道 DOM 被修改了。下次渲染发生时,React 将用它认为 DOM 节点的正确状态覆盖手动注入的内容。
这就是componentDidUpdate
来救援的地方!
基于 (dangerouslySetInnerHTML)。
这个道具完全可以满足您的需求。然而,他们命名它是为了传达应该谨慎使用
是的,直接设置元素的innerHTML属性与在React中使用dangerouslySetInnerHTML属性之间存在差异。
使用 innerHTML 的性能可能会较低,因为它涉及解析 HTML 字符串并相应地更新 DOM。此外,由于 React 不知道通过innerHTML 所做的更改,它可能无法有效地优化更新。
dangerouslySetInnerHTML 也会产生性能影响,因为 React 需要与其虚拟 DOM 协调机制分开处理内容。它可以绕过 React 在更新 DOM 时应用的一些优化。此外,dangerouslySetInnerHTML明确告诉React您正在自己管理内容并防止React干扰它。