【问题标题】:Replace part of string with tag in JSX用JSX中的标签替换部分字符串
【发布时间】:2015-05-27 06:16:03
【问题描述】:

我正在尝试用 JSX 标签替换部分字符串,如下所示:

render: function() {
    result = this.props.text.replace(":",<div className="spacer"></div>);
    return (
         <div>        
             {result}
         <div>        
    );
}

但鉴于this.props.textLorem : ipsum,它会导致

<div>
    Lorem [object Object] ipsum.
</div>

有没有办法解决这个问题或用 JSX 标签替换部分字符串?

【问题讨论】:

    标签: reactjs react-jsx


    【解决方案1】:

    接受的答案是 5 岁。对于这个问题,#3368 已创建,并基于一名从事 React 工作的 Facebook 员工提供的解决方案,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>
        );
      },
    });
    

    【讨论】:

    • 赞成。如果“内容”实际上包含一个冒号,则可以改进该示例。或者修改 reactStringReplace 行中的匹配器以匹配内容中的其他内容。
    • 这个库似乎占用了火柴周围的空间。
    • react-string-replace 太棒了!谢谢你。
    【解决方案2】:

    当您将 JSX 元素作为第二个参数传递给 replace() 时,该元素将转换为字符串,因为 replace() 需要一个字符串作为第二个参数。您需要做的是将您的字符串转换为字符串和 JSX 元素的数组。所以你的result 变量应该包含['Lorem ', &lt;div className="spacer"&gt;&lt;/div&gt;, ' 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>
        );
      }
    });
    

    【讨论】:

    • 安德斯,这太棒了!你知道除了在字符串中包含(和呈现)静态 HTML 之外,人们会如何做同样的事情?如果 Lorem 被包裹在 DIV 中,则在危险的 SetInnerHTML 中渲染 { result } 会带来各种(预期的)麻烦。
    • @MagnusEngdal 接受的答案是两年前。我今天遇到了这个问题,根据我今天所做的研究,我相信我的答案是解决这个问题的最佳方法。
    • React.createClass 自 v 15.5.0 起已被弃用,有任何替代解决方案吗?
    【解决方案3】:

    为 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;
      });
    };
    
    

    【讨论】:

    • 这是金子!然而,最好的做法是告诉你的脚本实际做了什么以及如何做。 :)
    【解决方案4】:

    以下内容也应该有效(假设 ES6),唯一的细微差别是文本实际上是包裹在 DIV 元素中而不是在它之前,假设您要使用 CSS 作为实际间距,这不应该是问题。

    const result = this.props.text.split(':').map(t => {
      return <div className='textItem'>{t}</div>;
    });
    

    【讨论】:

    • 结果将缺少分隔符 div,因为您没有用任何东西替换冒号。
    • 我不能用像'HTML:XML'这样的字符串来做到这一点,它是由html标签包装的
    【解决方案5】:

    你们使用的是复杂的方法,请保持简单:

    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 />);
    

    【讨论】:

    • 这与我所寻找的非常接近。但是有几个问题:这会在末尾添加一个我们不想要的额外元素,并且result 的范围不起作用。如果在循环外返回它,则需要在循环之前声明它。这就是我的选择:function replaceJSX(str, find, replace) { const parts = str.split(find); const result = []; for (let i = 0; i &lt; parts.length; i++) { result.push(parts[i]); if (i &lt; parts.length - 1) result.push(replace); } return result; }
    【解决方案6】:

    我已经开始遵循不包含第三方库或正则表达式的简单解决方案,也许它仍然可以帮助某人。

    主要只是使用.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
            }} />
        )
    }
    

    【讨论】:

      【解决方案7】:

      经过一些研究,我发现现有的库不符合我的要求。所以,当然,我自己写了:

      https://github.com/EfogDev/react-process-string

      它非常易于使用。您的案例:

      let result = processString({
          regex: /:/gim,
          fn: () => <div className="spacer"></div>
      })(this.props.test);
      

      【讨论】:

        【解决方案8】:

        除了这个解决方案之外,WEB 世界上没有任何东西对我有用 - 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]',
        });
        

        【讨论】:

          【解决方案9】:

          我有一个更常见的任务 - 用自定义标签包装所有(英文)单词。 我的解决方案:

          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>

          【讨论】:

            【解决方案10】:

            类似这样的:

            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
            }
            

            【讨论】:

              【解决方案11】:

              如果您还希望能够在替换中进行替换(例如,突出显示 url 中的搜索词),请查看我创建的这个节点模块 - https://github.com/marcellosachs/react-string-replace-recursively

              【讨论】:

                【解决方案12】:

                钩子示例:

                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
                }
                

                【讨论】:

                  【解决方案13】:

                  我认为这是最轻巧的完美解决方案:

                  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>
                      );
                    }
                  

                  这是一个有效的example

                  【讨论】:

                  • 尝试搜索字符串的最后几个字符。你的函数会截断它。
                  【解决方案14】:

                  我只是一个编写的函数助手,用于将一些文本、组件甚至 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://stackoverflow.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://stackoverflow.com/users/64730/magnus-engdal" title="Magnus Engdal">Magnus Engdal</a>, <span style="font-weight: bold;">This would be your solution.</span>, Enjoy!.</div>
                  

                  【讨论】:

                    【解决方案15】:

                    在我的例子中,我使用 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 src="${url}" target="_blank" rel="noopener noreferrer">${url}</a>`;
                    });
                    
                    export const TextRenderer: React.FC<TextRendererProps> = ({ text }) => {
                      return (
                        <span
                          dangerouslySetInnerHTML={{
                            __html: parser.render(text),
                          }}
                        />
                      );
                    };
                    
                    

                    您只需写parser.addRule()即可轻松添加替换规则。

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2021-03-25
                      • 1970-01-01
                      • 2012-07-17
                      • 1970-01-01
                      相关资源
                      最近更新 更多