今天服务端的同学想通过后端返回的字符串,通过
br
标签换行处理,但是发现了在前端并不能如愿的换行,这是为什么呢?我们是基于React库来开发前端页面的。
问题解决原因
其实用JS操作原生DOM场景下,我们可以使用
textContent
和
innerHTML
两个API为我们的HTML元素添加内容,
textContent
可以直接将文本内容添加到元素中,
innerHTML
则会将文本内容解析,再添加到内容中。
我们来看下这段代码执行的结果。
document.getElementById("p1").innerHTML = "123</br>123"
document.getElementById("p2").textContent = "123</br>123"
从图中我们不难发现使用innerHTML的元素换行了。
React是怎么生成的文本内容
通常,我们在React中使用的文本内容都会使用textContent生成文本
在React源码中我们可以找到如下代码
var setTextContent = function (node, text) {
if (text) {
var firstChild = node.firstChild;
if (firstChild && firstChild === node.lastChild && firstChild.nodeType === TEXT_NODE) {
firstChild.nodeValue = text;
return;
node.textContent = text;
var DANGEROUSLY_SET_INNER_HTML = 'dangerouslySetInnerHTML';
if (propKey === STYLE) {
setValueForStyles(domElement, propValue);
} else if (propKey === DANGEROUSLY_SET_INNER_HTML) {
setInnerHTML(domElement, propValue);
} else if (propKey === CHILDREN) {
setTextContent(domElement, propValue);
} else {
setValueForProperty(domElement, propKey, propValue, isCustomComponentTag);
if (propKey === CHILDREN) {
if (typeof nextProp === "string") {
var canSetTextContent = tag !== "textarea" || nextProp !== "";
if (canSetTextContent) {
setTextContent(domElement, nextProp);
} else if (typeof nextProp === "number") {
setTextContent(domElement, "" + nextProp);
如果我们需要在使用html文本元素怎么办呢?这时候我们的主角登场了。
dangerouslySetInnerHTML
我们在React官方文档中可以找到如下描述
dangerouslySetInnerHTML
是 React 为浏览器 DOM 提供 innerHTML
的替换方案。通常来讲,使用代码直接设置 HTML 存在风险,因为很容易无意中使用户暴露于跨站脚本(XSS)的攻击。因此,你可以直接在 React 中设置 HTML,但当你想设置 dangerouslySetInnerHTML
时,需要向其传递包含 key 为 __html
的对象,以此来警示你。
在React中我们可以看到如下的代码
if (props.dangerouslySetInnerHTML != null) {
if (!(props.children == null)) {
throw Error(
"Can only set one of `children` or `props.dangerouslySetInnerHTML`."
var setInnerHTML = createMicrosoftUnsafeLocalFunction(function (node, html) {
if (node.namespaceURI === Namespaces.svg) {
if (!("innerHTML" in node)) {
reusableSVGContainer =
reusableSVGContainer || document.createElement("div");
reusableSVGContainer.innerHTML =
"<svg>" + html.valueOf().toString() + "</svg>";
var svgNode = reusableSVGContainer.firstChild;
while (node.firstChild) {
node.removeChild(node.firstChild);
while (svgNode.firstChild) {
node.appendChild(svgNode.firstChild);
return;
node.innerHTML = html;
强调该方式存在风险,慎用。容易造成跨站脚本(XSS)攻击,如下面这段代码
const App = () => {
return <div dangerouslySetInnerHTML={{ __html: `<script>console.log('danger')</script>` }}></div>;
ReactDOM.render(<App />, document.getElementById("root"));
我们在控制台中可以看到这段script代码被打印了
