使用 JSX 动态添加 HTML 标记



在下面的示例中,我想找到分隔符中的所有字符串:;并在每个匹配项周围用HTML Mark标签替换它们。如果它工作正常,由于 Mark 标记,这些字符串应以黄色突出显示。相反,我的标签没有展开。有没有办法在JSX中做到这一点?

function App() {
let inputStr = 'This is a :test; of :highlighting;'
return (
<div>
{HighlightText(inputStr)}   
</div>
);
}
function HighlightText(str) {
let MyTag = 'Mark';
var matches = str.split(/[:;]/);
let outputStr = '';
matches.forEach(m => {
const test = ':' + m + ';';
if (str.includes(test)) {
outputStr += <MyTag> + m + </MyTag>;
} else {
outputStr += m;
}
});
return outputStr;
}
ReactDOM.render(
<App />,
document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="react"></div>

正如在另一个答案的评论中所说,出于安全考虑,我会避免dangerouslySetInnerHTML

相反,您可以将字符串分解为突出显示和非突出显示的子字符串数组,并分别将它们呈现为<mark>或常规<span>元素:

const { render } = ReactDOM,
rootNode = document.getElementById('root'),

testString = `This is a :test; of :highlighting;`

const App = () => {
const subStrings = testString.split(/(:.*?;)/)
return (
<div>
{
subStrings.map((s,key) => 
/(:.*;)/.test(s) ? 
<mark {...{key}}>{s.slice(1,-1)}</mark> :
<span>{s}</span>
)
}
</div>
)
}

render (
<App />,
rootNode
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.11.0/umd/react-dom.production.min.js"></script><div id="root"></div>

/:([^:;]*);/gString.prototype.split()一起使用来获取如下所示的数组:

["This is a ", "test", " of ", "highlighting", ""]

然后,您可以使用Array.prototype.flatMap()对其进行分组,如下所示:

[["This is a ", "test"], [" of ", "highlighting"], [""]]

最后,您可以使用Array.prototype.map()为上面的每个内部数组返回一个<React.Fragment />

ReactDOM.render(<App />, document.getElementById('react'));
function App() {
const inputStr = 'This is a :test; of :highlighting;';
return (
<div>{highlightText(inputStr)}</div>
);
}
function highlightText(str) {
const MyTag = 'Mark';
const matches = str.split(/:([^:;]*);/g);
const groups = matches.flatMap(
(value, index, array) => (
index % 2 === 0
? [array.slice(index, index + 2)]
: []
)
);
return groups.map(
([prefix, text], index) => (
<React.Fragment key={index}>
{prefix} {text && <MyTag>{text}</MyTag>}
</React.Fragment>
)
);
}
// example function demonstrating that `MyTag` resolves to `<Mark />`
function Mark({ children }) {
return (
<mark>{children}</mark>
);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="react"></div>

最新更新