我有一个React组件,我想为其道具分配一个包含JavaScript变量和HTML实体的字符串。
我尝试过的一些方法导致HTML实体被转义。例如,从字面上呈现为" "而不是" –"。
有没有办法让HTML实体在分配给React道具的JSX动态内容块中呈现为未转义?
尝试了
使用模板文字尝试:
...
问题:在渲染的输出中,的字面显示为" ",而不是" –"。
尝试构建一些不带引号的简单JSX:
问题:这在编译时失败,出现语法错误。
通过将JSX包装在元素中来尝试解决语法错误:
{name} {description}} ...
问题:可以,但是我宁愿避免在渲染输出中出现多余的元素。
尝试将HTML实体替换为Unicode数字字符引用:
问题:
这可行,但是(我认为)使代码少了一点
可读的。 (更明显的是," ndash"而不是" 2013"
代表一个破折号。)
同样,这涉及到+-运算符的串联,这会在我团队的JSLint检查器中触发Unexpected string concatenation prefer-template错误。使用字符串插值的解决方案会更好。
的子元素上的dangerouslySetInnerHTML是否有效?
将其分配给变量,然后使用它:let temp_str = $ {name} $ {description}``
@Tony:在title属性中使用。
@ T.J.Crowder我看到了title道具,但是(也许是错误的?)假设将呈现一些实际元素,例如h1,div,p等。
如果您用一个最小的可重现的示例演示问题来更新您的问题,这将对人们有所帮助,最好是使用Stack Snippets([<>]工具栏按钮)可运行的示例。堆栈片段支持React,包括JSX;这是怎么做的。
@Tony:考虑到span起作用的事情,您可能是对的。但是,在prop中允许HTML,然后使用dangerouslySetInnerHTML将会很危险。 :-D
@ T.J。Crowder哦,绝对可以!
Im AGAINS React在字符串变量中用–替换了,因为当您希望按原样显示字符串时(例如,显示用户评论),此功能需要对其进行预处理。这种替换仅适用于JSX(几乎是HTML)。
您可以使用Fragment避免多余的span:
{name} {description}>} ...
这个功能是在React 16.2中引入的。
请参阅文档
我同意@samanime的观点,使用实际字符最适合简单的情况,但是如果您的内容真正是动态的,我宁愿使用Fragment而不是entityToChar或dangerouslySetInnerHTML方法。
以下是一些选项(我不久前在较笼统的答案中概述了这些选项):
最简单-使用Unicode
更安全-在Javascript字符串中为实体使用Unicode数字。
要么
不得已-使用dragonallySetInnerHTML插入原始HTML。
title={`${name} ${description}`}
与:
const MyPanel = (props) => {
return (
{props.title}
)
}
const MyPanelwithDangerousHTML = (props) => {
return (
)
}
var description ="description";
var name ="name";
ReactDOM.render(
, document.getElementById("option1"));
ReactDOM.render(
, document.getElementById("option2"));
ReactDOM.render(
, document.getElementById("option3"));
ReactDOM.render(
, document.getElementById("option4"));
这是React关于HTML实体的文档:JSX陷阱
其中,最好使用实际字符而不是HTML实体:
如果由于HTML实体是动态的而不能这样做(这不仅仅是硬编码的破折号),则可以翻译该实体。这是一个可以执行此操作的小功能:
const entityToChar = str => {
const textarea = document.createElement('textarea');
textarea.innerHTML = str;
return textarea.value;
}
然后,您可以像这样使用它:
当然,问题在于,就像dangerouslySetInnerHTML一样,这意味着组件很高兴地呈现通过道具接收到的HTML内容,就像dangerouslySetInnerHTML一样,这是危险的。 :-)
它比dangerouslySetInnerHTML好一点,因为它随后会以textarea值的形式返回,这会剥离很多HTML。
由于您可能不想在title道具中允许使用任意URL,因此我很想为自己编写一个仅处理将字符实体转换为等效Unicode字符的函数。有点像" HTML-lite"。 :-)实际上,命名引用并不多;和数字的很容易:
const named = {
"ndash":"–", // or"\u2013"
"mdash":"—", // or"\u2014"
"nbsp":"" // or"\u00A0"
// ...
};
// Obviously this is a SKETCH, not production code!
function convertCharEntities(str) {
return str.replace(/&([^ ;&]+);/g, (_, ref) => {
let ch;
if (ref[0] ==="#") {
let num;
if (ref[0].toLowerCase() ==="x") {
num = parseInt(ref.substring(2), 16);
} else {
num = parseInt(ref, 10);
}
ch = String.fromCodePoint(num);
} else {
ch = named[ref.toLowerCase()];
}
return ch ||"";
});
}
然后在渲染该道具时使用它:
class Example extends React.Component {
render() {
return {convertCharEntities(this.props.title ||"")};
}
}
完整直播示例:
const named = {
"ndash":"–", // or"\u2013"
"mdash":"—", // or"\u2014"
"nbsp":"" // or"\u00A0"
// ...
};
// Obviously this is a SKETCH, not production code!
function convertCharEntities(str) {
return str.replace(/&([^ ;&]+);/g, (_, ref) => {
let ch;
if (ref[0] ==="#") {
let num;
if (ref[0].toLowerCase() ==="x") {
num = parseInt(ref.substring(2), 16);
} else {
num = parseInt(ref, 10);
}
ch = String.fromCodePoint(num);
} else {
ch = named[ref.toLowerCase()];
}
return ch ||"";
});
}
class Example extends React.Component {
render() {
return {convertCharEntities(this.props.title ||"")};
}
}
ReactDOM.render(
,
document.getElementById("root")
);
请注意,标签未作为标签输出,但已处理实体。
不知道的工作方式,我只能推测您可以执行以下操作:
...
MyPanel.js
render() {
const { title } = this.props;
return ;
}