用 JSX 中的标签替换部分字符串
Replace part of string with tag in JSX
我正在尝试用 JSX 标签替换部分字符串,如下所示:
render: function() {
result = this.props.text.replace(":",<div className="spacer"></div>);
return (
<div>
{result}
<div>
);
}
但是考虑到 this.props.text
是 Lorem : ipsum
,结果是
<div>
Lorem [object Object] ipsum.
</div>
有没有办法解决这个问题或用 JSX 标签替换部分字符串的其他方法?
当您将 JSX 元素作为第二个参数传递给 replace()
时,该元素将转换为字符串,因为 replace()
需要将字符串作为第二个参数。您需要做的是将字符串转换为字符串数组和 JSX 元素。所以你的 result
变量应该包含类似 ['Lorem ', <div className="spacer"></div>, ' ipsum']
.
的东西
像这样:
function flatMap(array, fn) {
var result = [];
for (var i = 0; i < array.length; i++) {
var mapping = fn(array[i]);
result = result.concat(mapping);
}
return result;
}
var Comp = React.createClass({
render: function () {
var result = 'Lorem : ipsum';
result = flatMap(result.split(':'), function (part) {
return [part, <div>spacer</div>];
});
// Remove the last spacer
result.pop();
return (
<div>
{result}
</div>
);
}
});
以下内容也应该有效(假设 ES6),唯一的细微差别是文本实际上包裹在 DIV 元素内,而不是前面,假设您要使用 CSS对于实际间距,这应该不是问题。
const result = this.props.text.split(':').map(t => {
return <div className='textItem'>{t}</div>;
});
如果您还希望能够在替换中进行替换(例如,在 url 中突出显示搜索词),请查看我创建的这个节点模块 - https://github.com/marcellosachs/react-string-replace-recursively
我有一个更常见的任务 - 用自定义标签包装所有(英文)单词。
我的解决方案:
class WrapWords extends React.Component {
render() {
const text = this.props.text;
const isEnglishWord = /\b([-'a-z]+)\b/ig;
const CustomWordTag = 'word';
const byWords = text.split(isEnglishWord);
return (
<div>
{
byWords.map(word => {
if (word.match(isEnglishWord)) {
return <CustomWordTag>{word}</CustomWordTag>;
}
return word;
})
}
</div>
);
}
}
// Render it
ReactDOM.render(
<WrapWords text="Argentina, were playing: England in the quarter-finals (the 1986 World Cup in Mexico). In the 52nd minute the Argentinian captain, Diego Maradona, scored a goal." />,
document.getElementById("react")
);
<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>
<div id="react"></div>
经过一些研究,我发现现有的库不符合我的要求。所以,当然,我自己写了:
https://github.com/EfogDev/react-process-string
非常容易使用。您的案例示例:
let result = processString({
regex: /:/gim,
fn: () => <div className="spacer"></div>
})(this.props.test);
接受的答案是 5 岁。针对此问题,创建了 #3368 was created and based on the solution provided by a Facebook employee working on React, react-string-replace。
使用 react-string-replace,这是解决问题的方法
const reactStringReplace = require('react-string-replace');
const HighlightNumbers = React.createClass({
render() {
const content = 'Hey my number is 555:555:5555.';
return (
<span>
{reactStringReplace(content, ':', (match, i) => (
<div className="spacer"></div>
))}
</span>
);
},
});
钩子示例:
import React, { useEffect, useState, useRef } from 'react'
export function Highlight({ value, highlightText }) {
const [result, resultSet] = useState(wrap())
const isFirstRun = useRef(true)
function wrap() {
let reg = new RegExp('(' + highlightText + ')', 'gi')
let parts = value.split(reg)
for (let i = 1; i < parts.length; i += 2) {
parts[i] = (
<span className='highlight' key={i}>
{parts[i]}
</span>
)
}
return <div>{parts}</div>
}
useEffect(() => {
//skip first run
if (isFirstRun.current) {
isFirstRun.current = false
return
}
resultSet(wrap())
}, [value, highlightText])
return result
}
为 jsx 编写了实用函数。
const wrapTags = (text: string, regex: RegExp, className?: string) => {
const textArray = text.split(regex);
return textArray.map(str => {
if (regex.test(str)) {
return <span className={className}>{str}</span>;
}
return str;
});
};
我已经开始遵循不包括第三方库或正则表达式的简单解决方案,也许它仍然可以帮助某人。
主要是用.replace()把字符串替换成正则的html写成字符串,比如:
text.replace('string-to-replace', '<span class="something"></span>')
然后在元素内使用 dangerouslySetInnerHTML
渲染它。
完整示例:
const textToRepace = 'Insert :' // we will replace : with div spacer
const content = textToRepace.replace(':', '<div class="spacer"></div>') : ''
// then in rendering just use dangerouslySetInnerHTML
render() {
return(
<div dangerouslySetInnerHTML={{
__html: content
}} />
)
}
我认为这是最轻的完美解决方案:
render() {
const searchValue = "an";
const searchWordRegex = new RegExp(searchValue, "gi");
const text =
"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text";
return (
<div>
{text.split(searchWordRegex).length > 1
? text.split(searchWordRegex).map((chunk, index) => {
if (chunk !== "") {
return index === 0 &&
! new RegExp("^" + searchValue, "gi").test(text) ? (
chunk
) : (
<span key={index}>
<span
className="highlight"
style={{
fontWeight: "bold"
}}
>
{searchValue.charAt(0).toUpperCase() +
searchValue.slice(1)}
</span>
{chunk}
</span>
);
} else {
return null;
}
})
: text}
</div>
);
}
and here is a working example
除了这个解决方案外,WEB globe 对我没有任何帮助 - https://www.npmjs.com/package/regexify-string
使用 React,字符串并且没有任何额外的依赖项
regexifyString({
pattern: /\[.*?\]/gim,
decorator: (match, index) => {
return (
<Link
to={SOME_ROUTE}
onClick={onClick}
>
{match}
</Link>
);
},
input: 'Some text with [link]',
});
你们正在使用复杂的方法,保持简单:
function replaceJSX(str, find, replace) {
let parts = str.split(find);
for(let i = 0, result = []; i < parts.length; i++) {
result.push(parts[i]);
result.push(replace);
}
return result;
}
用法
replaceJSX(variable, ":", <br />);
像这样:
function replaceByComponent(string, component) {
const variable = string.substring(
string.lastIndexOf("{{") + 2,
string.lastIndexOf("}}")
);
const strParts = string.split(`{{${variable}}}`);
const strComponent = strParts.map((strPart, index) => {
if(index === strParts.length - 1) {
return strPart
}
return (
<>
{strPart}
<span>
{component}
</span>
</>
)
})
return strComponent
}
我只是编写了一个函数助手,用于将一些文本、组件甚至 HTML 替换为我的项目的模板字符串。结果很好很顺利。
const replaceJSX = (str, replacement) => {
const result = [];
const keys = Object.keys(replacement);
const getRegExp = () => {
const regexp = [];
keys.forEach((key) => regexp.push(`{${key}}`));
return new RegExp(regexp.join('|'));
};
str.split(getRegExp()).forEach((item, i) => {
result.push(item, replacement[keys[i]]);
});
return result;
};
用法:
const User = ({ href, name }) => {
return (
<a href={href} title={name}>
{name}
</a>
);
};
const string = 'Hello {component}, {html}, {string}';
return (
<div>
{replaceJSX(string, {
component: (
<User
href='https://whosebug.com/users/64730/magnus-engdal'
name='Magnus Engdal'
/>
),
html: (
<span style={{ fontWeight: 'bold' }}>
This would be your solution
</span>
),
string: 'Enjoy!',
})}
</div>
)
你会得到这样的东西:
<div>Hello <a href="https://whosebug.com/users/64730/magnus-engdal" title="Magnus Engdal">Magnus Engdal</a>, <span style="font-weight: bold;">This would be your solution.</span>, Enjoy!.</div>
就我而言,我使用 React,我想用锚标记替换文本中的 url。
在我的解决方案中,我使用了两个库。
并编写了这段代码。
/* eslint-disable react/no-danger */
import React from 'react';
import { Parser } from 'simple-text-parser';
import urlRegex from 'url-regex';
type TextRendererProps = { text: string };
const parser = new Parser();
const re = urlRegex();
parser.addRule(re, (url) => {
return `<a href="${url}" target="_blank" rel="noopener noreferrer">${url}</a>`;
});
export const TextRenderer: React.FC<TextRendererProps> = ({ text }) => {
return (
<span
dangerouslySetInnerHTML={{
__html: parser.render(text),
}}
/>
);
};
您只需编写 parser.addRule()
.
即可轻松添加替换规则
我正在尝试用 JSX 标签替换部分字符串,如下所示:
render: function() {
result = this.props.text.replace(":",<div className="spacer"></div>);
return (
<div>
{result}
<div>
);
}
但是考虑到 this.props.text
是 Lorem : ipsum
,结果是
<div>
Lorem [object Object] ipsum.
</div>
有没有办法解决这个问题或用 JSX 标签替换部分字符串的其他方法?
当您将 JSX 元素作为第二个参数传递给 replace()
时,该元素将转换为字符串,因为 replace()
需要将字符串作为第二个参数。您需要做的是将字符串转换为字符串数组和 JSX 元素。所以你的 result
变量应该包含类似 ['Lorem ', <div className="spacer"></div>, ' ipsum']
.
像这样:
function flatMap(array, fn) {
var result = [];
for (var i = 0; i < array.length; i++) {
var mapping = fn(array[i]);
result = result.concat(mapping);
}
return result;
}
var Comp = React.createClass({
render: function () {
var result = 'Lorem : ipsum';
result = flatMap(result.split(':'), function (part) {
return [part, <div>spacer</div>];
});
// Remove the last spacer
result.pop();
return (
<div>
{result}
</div>
);
}
});
以下内容也应该有效(假设 ES6),唯一的细微差别是文本实际上包裹在 DIV 元素内,而不是前面,假设您要使用 CSS对于实际间距,这应该不是问题。
const result = this.props.text.split(':').map(t => {
return <div className='textItem'>{t}</div>;
});
如果您还希望能够在替换中进行替换(例如,在 url 中突出显示搜索词),请查看我创建的这个节点模块 - https://github.com/marcellosachs/react-string-replace-recursively
我有一个更常见的任务 - 用自定义标签包装所有(英文)单词。 我的解决方案:
class WrapWords extends React.Component {
render() {
const text = this.props.text;
const isEnglishWord = /\b([-'a-z]+)\b/ig;
const CustomWordTag = 'word';
const byWords = text.split(isEnglishWord);
return (
<div>
{
byWords.map(word => {
if (word.match(isEnglishWord)) {
return <CustomWordTag>{word}</CustomWordTag>;
}
return word;
})
}
</div>
);
}
}
// Render it
ReactDOM.render(
<WrapWords text="Argentina, were playing: England in the quarter-finals (the 1986 World Cup in Mexico). In the 52nd minute the Argentinian captain, Diego Maradona, scored a goal." />,
document.getElementById("react")
);
<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>
<div id="react"></div>
经过一些研究,我发现现有的库不符合我的要求。所以,当然,我自己写了:
https://github.com/EfogDev/react-process-string
非常容易使用。您的案例示例:
let result = processString({
regex: /:/gim,
fn: () => <div className="spacer"></div>
})(this.props.test);
接受的答案是 5 岁。针对此问题,创建了 #3368 was created and based on the solution provided by a Facebook employee working on React, react-string-replace。
使用 react-string-replace,这是解决问题的方法
const reactStringReplace = require('react-string-replace');
const HighlightNumbers = React.createClass({
render() {
const content = 'Hey my number is 555:555:5555.';
return (
<span>
{reactStringReplace(content, ':', (match, i) => (
<div className="spacer"></div>
))}
</span>
);
},
});
钩子示例:
import React, { useEffect, useState, useRef } from 'react'
export function Highlight({ value, highlightText }) {
const [result, resultSet] = useState(wrap())
const isFirstRun = useRef(true)
function wrap() {
let reg = new RegExp('(' + highlightText + ')', 'gi')
let parts = value.split(reg)
for (let i = 1; i < parts.length; i += 2) {
parts[i] = (
<span className='highlight' key={i}>
{parts[i]}
</span>
)
}
return <div>{parts}</div>
}
useEffect(() => {
//skip first run
if (isFirstRun.current) {
isFirstRun.current = false
return
}
resultSet(wrap())
}, [value, highlightText])
return result
}
为 jsx 编写了实用函数。
const wrapTags = (text: string, regex: RegExp, className?: string) => {
const textArray = text.split(regex);
return textArray.map(str => {
if (regex.test(str)) {
return <span className={className}>{str}</span>;
}
return str;
});
};
我已经开始遵循不包括第三方库或正则表达式的简单解决方案,也许它仍然可以帮助某人。
主要是用.replace()把字符串替换成正则的html写成字符串,比如:
text.replace('string-to-replace', '<span class="something"></span>')
然后在元素内使用 dangerouslySetInnerHTML
渲染它。
完整示例:
const textToRepace = 'Insert :' // we will replace : with div spacer
const content = textToRepace.replace(':', '<div class="spacer"></div>') : ''
// then in rendering just use dangerouslySetInnerHTML
render() {
return(
<div dangerouslySetInnerHTML={{
__html: content
}} />
)
}
我认为这是最轻的完美解决方案:
render() {
const searchValue = "an";
const searchWordRegex = new RegExp(searchValue, "gi");
const text =
"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text";
return (
<div>
{text.split(searchWordRegex).length > 1
? text.split(searchWordRegex).map((chunk, index) => {
if (chunk !== "") {
return index === 0 &&
! new RegExp("^" + searchValue, "gi").test(text) ? (
chunk
) : (
<span key={index}>
<span
className="highlight"
style={{
fontWeight: "bold"
}}
>
{searchValue.charAt(0).toUpperCase() +
searchValue.slice(1)}
</span>
{chunk}
</span>
);
} else {
return null;
}
})
: text}
</div>
);
}
and here is a working example
除了这个解决方案外,WEB globe 对我没有任何帮助 - https://www.npmjs.com/package/regexify-string
使用 React,字符串并且没有任何额外的依赖项
regexifyString({
pattern: /\[.*?\]/gim,
decorator: (match, index) => {
return (
<Link
to={SOME_ROUTE}
onClick={onClick}
>
{match}
</Link>
);
},
input: 'Some text with [link]',
});
你们正在使用复杂的方法,保持简单:
function replaceJSX(str, find, replace) {
let parts = str.split(find);
for(let i = 0, result = []; i < parts.length; i++) {
result.push(parts[i]);
result.push(replace);
}
return result;
}
用法
replaceJSX(variable, ":", <br />);
像这样:
function replaceByComponent(string, component) {
const variable = string.substring(
string.lastIndexOf("{{") + 2,
string.lastIndexOf("}}")
);
const strParts = string.split(`{{${variable}}}`);
const strComponent = strParts.map((strPart, index) => {
if(index === strParts.length - 1) {
return strPart
}
return (
<>
{strPart}
<span>
{component}
</span>
</>
)
})
return strComponent
}
我只是编写了一个函数助手,用于将一些文本、组件甚至 HTML 替换为我的项目的模板字符串。结果很好很顺利。
const replaceJSX = (str, replacement) => {
const result = [];
const keys = Object.keys(replacement);
const getRegExp = () => {
const regexp = [];
keys.forEach((key) => regexp.push(`{${key}}`));
return new RegExp(regexp.join('|'));
};
str.split(getRegExp()).forEach((item, i) => {
result.push(item, replacement[keys[i]]);
});
return result;
};
用法:
const User = ({ href, name }) => {
return (
<a href={href} title={name}>
{name}
</a>
);
};
const string = 'Hello {component}, {html}, {string}';
return (
<div>
{replaceJSX(string, {
component: (
<User
href='https://whosebug.com/users/64730/magnus-engdal'
name='Magnus Engdal'
/>
),
html: (
<span style={{ fontWeight: 'bold' }}>
This would be your solution
</span>
),
string: 'Enjoy!',
})}
</div>
)
你会得到这样的东西:
<div>Hello <a href="https://whosebug.com/users/64730/magnus-engdal" title="Magnus Engdal">Magnus Engdal</a>, <span style="font-weight: bold;">This would be your solution.</span>, Enjoy!.</div>
就我而言,我使用 React,我想用锚标记替换文本中的 url。
在我的解决方案中,我使用了两个库。
并编写了这段代码。
/* eslint-disable react/no-danger */
import React from 'react';
import { Parser } from 'simple-text-parser';
import urlRegex from 'url-regex';
type TextRendererProps = { text: string };
const parser = new Parser();
const re = urlRegex();
parser.addRule(re, (url) => {
return `<a href="${url}" target="_blank" rel="noopener noreferrer">${url}</a>`;
});
export const TextRenderer: React.FC<TextRendererProps> = ({ text }) => {
return (
<span
dangerouslySetInnerHTML={{
__html: parser.render(text),
}}
/>
);
};
您只需编写 parser.addRule()
.