如何使用替换为 React 中字符串的特定部分添加颜色?

IT技术 reactjs jsx
2022-07-06 01:16:47

我想把字符串中的所有数字都变成红色,然后用 React 渲染它。这是我正在尝试做的事情(我已经使用 App.js 制作了一个应用程序,create-react-app并用我自己的内容替换了 App.js 的内容):

import React, { Component } from 'react';
import './App.css';

class App extends Component {
  render() {
    const str = 'foo123bar';

    const strColor = 
      str.replace(/\d+/, match => <span style={{color: 'red'}}> {match} </span> );

    return (
      <div className="App">
        {strColor}
      </div>
    );
  }
}

export default App;

结果foo[object Object]bar,在视口中只渲染了线条。

那么内联样式应该如何添加到 JSX 中呢?

3个回答

我能够通过使用“dangerouslySetInnerHTML”来解决这个问题。

class App extends React.Component {
  render() {
      let str = 'foo123bar';

      const strColor = str.replace(/\d+/, match => `<span style="color: red">${match} </span>` );

    return (
        <div className="App"
         dangerouslySetInnerHTML={{__html: 
          strColor}}>
      </div>
);

} }

“那么内联样式应该如何添加到 JSX 中呢?”

要回答您提出的问题,您的线路:

const strColor = str.replace(/\d+/, match => <span style={{color: 'red'}}> {match} </span> );

正在返回一个字符串 - 所以对象语句style={{color: 'red'}}> 不会被转义。

改为使用字符串定义添加内联样式,引用双引号并删除花括号:
<span style="color: red"> {match} </span>

您可以通过使用逗号分隔键:值对来添加更多样式:
<span style="color: red, text-decoration: underline"> {match} </span>


请注意,这将不起作用
您真正要回答的问题是如何用组件替换字符串的一部分(在本例中为<span>带有样式的标记。此问题记录在 react github 问题页面中,请注意有很多选项不需要您危险地设置您的内部 HTML,如前面几个答案中所述:https ://github.com/facebook/react/issues/3386

您不能将 HTML 插入到字符串中以使其在 React 中呈现,这是作为 XSS 的保护而存在的。

在这种情况下你可以做的事情是这样的:

const str = 'foo123bar';

const coloredStr = str.match(/\d+/);
const [before, after] = str.split(/\d+/)

return (
  <div className="App">
    {before}
    {coloredStr && coloredStr[0] && 
       <span style="color: red">{coloredStr[0]}</span>
    }
    {after}
  </div>
);

对于更复杂的示例,您将需要更复杂的逻辑。例如,可以设置多个部分的样式 - 您可以找到所有匹配的部分和不匹配的部分,并以正确的顺序将它们放入列表中,如果您使用跨度,请使用指示器。就像是:

list.map((elem) => elem.isColored ? <span style="color: red">{elem.value}</span> : elem.value)

编辑

如评论中所述,这是多个元素的实现:

const str = 'foo123bar456baz897ban';
let strCopy = str;
const list = [];

while(strCopy) {
    const text = strCopy.split(/\d+/, 1)[0];
    list.push(text);
    const match = strCopy.match(/\d+/);
    if (!match) {
        break;
    }
    list.push(match[0]);
    strCopy = strCopy.substring(match.index + match[0].length);
}

return (
  <div className="App">
    {list.map((elem, index) => index % 2 === 0
         ? elem
         : <span style="color: red">{elem}</span>
    )}
  </div>
);