[英]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.