【问题标题】:React: Highlight text between two indexesReact:突出显示两个索引之间的文本
【发布时间】:2020-04-26 13:45:17
【问题描述】:

因此,对于每个预测,谷歌放置自动完成 API 也会为每个预测返回匹配的子字符串。

输入:San 68

预测:旧金山 68

匹配的子串:[{ offset: 0, length: 3 }, { offset: 15, length: 2 }]

预期:旧金山旧金山68

我的目标是使用匹配的子字符串突出显示部分预测。现在有一些挑战。我可以使用replace 函数并将每个子字符串替换为<b>str</b>,但它返回一个字符串,这意味着除非我使用dangerouslySetInnerHTML,否则此方法不起作用。

我也不认为有办法替换多个子字符串。我尝试使用 reduce 函数,但在第一个循环之后它不会真正起作用,因为索引会出错。

const highlight = (text, matched_substrings) => {
  return matched_substrings.reduce((acc, cur) => {
    return acc.replace(
      acc.substring(cur.offset, cur.length),
      (str) => `<b>${str}</b>`
    )
  }, text)
}

那么有没有办法做到这一点?我认为 React 让这变得更加复杂。

【问题讨论】:

    标签: javascript reactjs google-places-api


    【解决方案1】:

    可能不是最好的解决方案,但绝对可以解决:) 先决条件是,matched_substrigs 数组必须按偏移量排序

    export const highlightText = (text, matched_substring, start, end) => {
        const highlightTextStart = matched_substring.offset;
        const highlightTextEnd = highlightTextStart + matched_substring.length;
    
        // The part before matched text
        const beforeText = text.slice(start, highlightTextStart);
    
        // Matched text
        const highlightedText = text.slice(highlightTextStart, highlightTextEnd);
    
        // Part after matched text
        // Till the end of text, or till next matched text
        const afterText = text.slice(highlightTextEnd, end || text.length);
    
        // Return in array of JSX elements
        return [beforeText, <strong>{highlightedText}</strong>, afterText];
    };
    
    export const highlight = (text, matched_substrings) => {
        const returnText = [];
    
        // Just iterate through all matches
        for (let i = 0; i < matched_substrings.length; i++) {
            const startOfNext = matched_substrings[i + 1]?.offset;
            if (i === 0) { // If its first match, we start from first character => start at index 0
                returnText.push(highlightText(text, matched_substrings[i], 0, startOfNext))
            } else { // If its not first match, we start from match.offset 
                returnText.push(highlightText(text, matched_substrings[i], matched_substrings[i].offset, startOfNext))
            }
        }
    
        return returnText.map((text, i) => <React.Fragment key={i}>{text}</React.Fragment>)
    };
    

    【讨论】:

      【解决方案2】:

      如果您不介意使用dangerouslySetInnerHTML,这里有一个解决方案

      const Highlight = ({ text, substrings }) => {
        const html = substrings.reduce((acc, cur, idx) => {
          return acc.replace(
            new RegExp(
              '(?<=^.{' + (cur.offset + idx * 17) + '})(.{' + cur.length + '})',
            ),
            (str) => `<strong>${str}</strong>`,
          )
        }, text)
        return <span dangerouslySetInnerHTML={{ __html: html }} />
      }
      

      这样使用

      <Highlight text={...} substrings={...} />
      

      【讨论】:

        猜你喜欢
        • 2013-03-31
        • 1970-01-01
        • 2015-11-12
        • 2016-07-31
        • 2020-08-13
        • 2020-08-12
        • 2018-01-06
        • 2018-01-09
        • 1970-01-01
        相关资源
        最近更新 更多