【问题标题】:Add HTML tags dynamically using JSX使用 JSX 动态添加 HTML 标签
【发布时间】:2020-05-13 20:54:15
【问题描述】:

在下面的示例中,我想查找分隔符内的所有字符串 :;并在每个匹配项周围用 HTML 标记标记替换它们。如果它正常工作,由于 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>

【问题讨论】:

    标签: javascript reactjs jsx


    【解决方案1】:

    正如 cmets 中对另一个答案所说,出于安全考虑,我会避免使用 dangerouslySetInnerHTML

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

    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
    )
    &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"&gt;&lt;/script&gt;&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.11.0/umd/react-dom.production.min.js"&gt;&lt;/script&gt;&lt;div id="root"&gt;&lt;/div&gt;

    【讨论】:

      【解决方案2】:

      使用/:([^:;]*);/gString.prototype.split() 得到这样的数组:

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

      然后你可以使用Array.prototype.flatMap()这样分组:

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

      最后你可以使用Array.prototype.map()为上面的每个内部数组返回一个&lt;React.Fragment /&gt;

      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>

      【讨论】:

        猜你喜欢
        • 2021-12-07
        • 1970-01-01
        • 2016-10-07
        • 2016-12-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-01-24
        相关资源
        最近更新 更多