“dangerouslySetInnerHTML到底有多危险?!”
需要使用dangerouslySetInnerHTML的情况。
我在React组件中写了这样的代码。
const mediaContent = getMediaContent();
return(
<div className="post_text">
{ mediaContent }
</div>
)
getMediaContent()是一个用于生成显示图像等内容的HTML的原始函数。mediaContent变量存储着HTML字符串。
虽然函数生成了HTML,但并不能直接用来显示图像。它只是将字符串展示出来,而不是在浏览器中解析显示图像。
我对此感到困惑,于是向ChatGPT咨询了一下。
在JavaScript(JSX)中,如果直接呈现HTML字符串,则会以字符串的形式显示。要将字符串呈现为HTML,需要使用dangerouslySetInnerHTML属性。
const mediaContent = getMediaContent();
return(
<div
className="post_text"
dangerouslySetInnerHTML={{ __html: mediaContent }}
/>
)
這樣一來,瀏覽正確無誤。然而,當我閱讀ChatGPT的回答時,對於一些可疑的屬性名稱感到有些不妥。
请注意,`dangerouslySetInnerHTML`正如其名称,存在安全风险。如果`mainText`中包含恶意脚本,则可能成为跨站脚本攻击(XSS)的目标。
嗯,只要getMediaContent()的来源明确就好。
如果出现不必要的标签,这就是一个问题。
事实上,这个故事还没有结束。接下来需要作为备忘录记录下来。
这个 dangerouslySetInnerHTML 是一个属性,所以必须与某些标签一起使用。换句话说,如果 mediaContent 生成的字符串包含了所有所需的标签,就会产生一个多余的标签。
这个多余的标签实际上是个问题。因为根据场景不同,由 mediaContent 生成的 DOM 元素会发生变化。这样就可能导致无法应用相应的 CSS。这是个大问题。
顺便提一下,可以通过引入WordPress提供的wp.element.Fragment来完成。
<Fragment
dangerouslySetInnerHTML={{ __html: mediaContent }}
/>
即使这样也不行。完全没有显示出来了。
在使用html-react-parser库时的应用方法。
但是,我们有一种避免的方法。
有一个名为html-react-parser的库。
首先,使用以下命令进行安装。
npm install html-react-parser
所以,如果在React组件中写成以下这样是可以的。看起来非常清晰,不是吗?
import parse from 'html-react-parser';
// ...
return (
<>
{parse(mediaItem)}
</>
);
因此,我认为使用html-react-parser是最佳选择。不过,即使使用这种方法
请注意包含不可靠的 HTML 字符串可能会带来的安全风险。如有需要,请进行适当的过滤处理。
– 来自ChatGPT的建议
在JSX中直接创建元素。
但是,根据条件可能有更简单的方法。
这种方法是直接在JSX中创建元素。
如果生成HTML的函数很复杂,就不能这样做,但是如果例如一个名为flg的状态变量为true,我们想在字符串中添加一个span标签来显示,那么可以这样做。
首先,让我们尝试一下这段代码。
const dispLabel = flg ? `${labelContent}<span>(${required.display})<span>` : labelContent;
return(
<label>
{dispLabel}
</label>
)
我试图使用模板文字直接生成和渲染字符串。这样做的话,
就是这样。所以
const dispLabel = flg ? `${labelContent}<span>(${required.display})<span>` : labelContent;
return(
<label
dangerouslySetInnerHTML={{ __html: dispLabel }}
/>
)
如果这样做能够成功,但原本就不应该以字符串形式生成dispLabel。
因此,
const dispLabel = required.flg ? <>{labelContent}<span>({required.display})</span></> : labelContent;
return(
<label>
{dispLabel}
</label>
)
这将起作用。
我会添加一点解释。
JSX(JavaScript XML)是React的一个扩展语法,它使得可以在JavaScript中编写HTML标签。
const element = <h1>Hello, world!</h1>;
当你写下这样的代码时,元素将会成为React能够理解的特殊对象。它是JavaScript对象表示的一种形式,React利用它来更新DOM。我们称之为”React元素”。
换句话说,我们只需要创建”React元素”而不是使用字符串,这样我们就能够更好地避免使用dangerouslySetInnerHTML。
这样做的好处应该是相当大的。