[英]React props: Using an HTML entity within JSX dynamic content?
我有一个React 组件,我想为它的 props 分配一个包含 JavaScript 变量和 HTML 实体的字符串。
我尝试过的一些方法导致 HTML 实体被转义。 例如, –
被逐字呈现为“ –
”而不是“ –
”。
有没有办法让 HTML 实体在分配给 React 道具的 JSX 动态内容块中呈现未转义?
尝试使用模板文字:
<MyPanel title={`${name} – ${description}`}> ... </MyPanel>
问题:在渲染输出中, –
字面意思是“ –
”而不是“ –
”。
尝试构造一些不带引号的简单 JSX:
<MyPanel title={{name} – {description}} ... </MyPanel>
问题:这在编译时因语法错误而失败。
尝试通过将 JSX 包装在<span />
元素中来解决语法错误:
<MyPanel title={<span>{name} – {description}</span>} ... </MyPanel>
问题:这可行,但我宁愿避免渲染输出中出现多余的<span />
元素。
尝试用 Unicode 数字字符引用替换 HTML 实体:
<MyPanel title={name + ' \u2013 ' + description} ... </MyPanel>
问题:
+
-operator 连接,这会在我团队的 JSLint 检查器中触发Unexpected string concatenation prefer-template
preferred Unexpected string concatenation prefer-template
错误; 使用字符串插值的解决方案会更好。您可以使用Fragment
避免多余的span
:
<MyPanel title={<>{name} – {description}</>} ... </MyPanel>
这个特性是在 React 16.2 中引入的。
查看文档
我同意@samanime 的观点,即使用实际字符最适合简单情况,但如果您的内容确实是动态的,我更愿意使用Fragment
而不是entityToChar
或dangerouslySetInnerHTML
的entityToChar
方法。
这里有一些选项(我在不久前的一个更一般的答案中概述了这些):
最简单 - 使用 Unicode
<MyPanel title={ `${name} – ${description}` } />
更安全 - 对 Javascript 字符串中的实体使用 Unicode 编号。
<MyPanel title={`${name} \– ${description}`} />
或者
<MyPanel title={`${name} ${String.fromCharCode(8211)} ${description}`} />
最后的手段 - 使用危险的 SetInnerHTML 插入原始 HTML。
title={`${name} – ${description}`}
和:
<div dangerouslySetInnerHTML={{__html: props.title}}></div>
const MyPanel = (props) => { return ( <div>{props.title}</div> ) } const MyPanelwithDangerousHTML = (props) => { return ( <div dangerouslySetInnerHTML={{__html: props.title}}></div> ) } var description = "description"; var name = "name"; ReactDOM.render(<MyPanel title={`${name} – ${description}`} /> , document.getElementById("option1")); ReactDOM.render(<MyPanel title={`${name} \– ${description}`} /> , document.getElementById("option2")); ReactDOM.render(<MyPanel title={`${name} ${String.fromCharCode(8211)} ${description}`} /> , document.getElementById("option3")); ReactDOM.render(<MyPanelwithDangerousHTML title={`${name} – ${description}`} /> , document.getElementById("option4"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.js"></script> <div id="option1"></div> <div id="option2"></div> <div id="option3"></div> <div id="option4"></div>
这是 React 关于 HTML 实体的文档: JSX Gotchas
其中,最好使用实际字符而不是 HTML 实体:
<MyPanel title={ `${name} – ${description}` } />
如果因为 HTML 实体是动态的(它不仅仅是硬编码的短划线)而不能这样做,则可以翻译该实体。 这是一个可以做到这一点的小函数:
const entityToChar = str => {
const textarea = document.createElement('textarea');
textarea.innerHTML = str;
return textarea.value;
}
然后像这样使用它:
<MyPanel title={ entityToChar(`${name} – ${description}`) } />
在不知道<MyPanel />
是如何工作的情况下,我只能推测您可以执行以下操作:
<MyPanel title={`${name} – ${description}`}> ... </MyPanel>
我的面板.js
render() {
const { title } = this.props;
return <div dangerouslySetInnerHTML={{ __html: title }} />;
}
由于您可能不希望在您的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 <div>{convertCharEntities(this.props.title || "")}</div>;
}
}
完整的现场示例:
const named = { "ndash": "–", // or "\–" "mdash": "—", // or "\—" "nbsp": " " // or "\ " // ... }; // 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 <div>{convertCharEntities(this.props.title || "")}</div>; } } ReactDOM.render( <Example title="Testing 1 2 3 — enh, you know the drill <script src='nefarious.js'><\\/script>" />, document.getElementById("root") );
<div id="root"></div><script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
请注意,标签不是作为标签输出,而是处理实体。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.