【问题标题】:Make letters from a word bold based on user input根据用户输入将单词中的字母加粗
【发布时间】:2020-12-08 08:43:43
【问题描述】:

我的应用中有一个搜索组件,当用户输入一些文本时,它会根据用户输入过滤数据并显示过滤数据列表。我想要做的是使用户搜索的文本在过滤后的数据中加粗。例如,如果我搜索 'Jo' ,过滤后的数据应显示为 John / Joseph / Joe Rogan

我可以想办法让整个单词加粗,但不能想办法只加粗用户输入的部分。

【问题讨论】:

  • 请向我们展示您目前拥有的内容,我们将尝试对其进行更新以满足您的要求 :)

标签: javascript html css reactjs


【解决方案1】:

很简单。只需使用粗体或强标记进行拆分和连接。

let searchStr = "Jo"
name.split(searchStr ).join('<b>'+ searchStr +'</b>');

let searchStr = "Jo";
let name = "John";

document.getElementById('res').innerHTML = name.split(searchStr).join('<b>'+ searchStr +'</b>');
<h2>Searching "Jo" in John</h2>
<p id="res"></p>

【讨论】:

  • 你不想在 React 中做 innerHTML 修改。
  • 这只是在 vanilla JS 中的演示,而不是在反应中。两者的逻辑是相同的。他只需要插入粗体标签的逻辑。大家都知道用dangerouslySetInnerHTML在react中设置一个HTML内容。
  • 您为什么要为此使用dangerouslySetInnerHTML?线索在标题中。这个问题明确提到它是任意用户输入。
  • 请看这个例子,为什么我们需要dangerouslySetInnerHTML - codesandbox.io/s/react-hooks-search-filter-4gnwc?file=/src/…。这正是他想要的。
  • @Prem 直到 OP 想要使用确实具有 HTML 标记的术语(或显示结果)进行搜索,并且 dangerouslySetInnerHTML 转向危险领域。
【解决方案2】:

您想根据搜索词更改过滤数据中每个字符串的呈现方式。

您可以使用搜索词创建一个正则表达式,然后根据该正则表达式为每个字符串添加&lt;strong&gt; 标签。

如果你不想使用dangerouslySetInnerHtml,那么你可以这样做:

const data = ["John", "Banjo", "Jojo", "Bob Jones", "John Johnson", "James"];

const searchTerm = "jo";

const searchTermRegex = new RegExp(
  // Escape special regex characters in the search term,
  // otherwise you will get an invalid regex
  `(${searchTerm.replace(/[.\\+*?[^\]$(){}=!<>|:-]/g, "\\$&")})`,
  "gi"
);

const getBoldFilteredText = (text, term) => {
  const substrings = text.split(searchTermRegex);
  return (
    <div>
      {substrings.map((substring) =>
        substring.toLowerCase() === term.toLowerCase() ? (
          <strong>{substring}</strong>
        ) : (
          substring
        )
      )}
    </div>
  );
};

return <div>{data.map((s) => getBoldFilteredText(s, searchTerm))}</div>;

【讨论】:

  • 这个答案解决了如何在 React 中渲染部分粗体文本的问题。您可以采用此示例并将其实现到您的应用程序中。我不会为你写出过滤逻辑、获取逻辑和构建一个完整的组件,因为你没有在你的问题中提供任何代码。很明显,搜索词只是你的状态值,它会随着用户输入而改变,你会在渲染数据之前过滤数据。
【解决方案3】:

这是一种使用dangerouslySetInnerHTML或让您面临XSS攻击的方法。

解释:String#split 带有正则表达式捕获组 (/(...)/) 在奇数索引处的结果中包含捕获的文本。例如,'baba'.split(/(b)/) 为您提供 ["", "b", "a", "b", "a"]。获得这些结果后,您可以将奇数(匹配)结果映射到 strong 元素,将偶数结果映射到 React.Fragments。

Demo

// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#Escaping
const regexEscape = str => str.replace(/[.*+\-?^${}()|[\]\\]/g, '\\$&')

const boldify = searchStr => targetStr => {
  return targetStr
    .split(new RegExp(`(${regexEscape(searchStr)})`, 'i'))
    .map((part, idx) =>
      idx % 2 ? (
        <strong key={idx}>{part}</strong>
      ) : (
        <React.Fragment key={idx}>{part}</React.Fragment>
      )
    )
}

const SearchForm = () => {
  const [searchStr, setSearchStr] = useState('');

  return (
    <form onSubmit={e => e.preventDefault()}>
      <input
        type='text'
        value={searchStr}
        onChange={e => setSearchStr(e.currentTarget.value)}
      />

      <ul>
        {list.map(item => {
          return <li>{boldify(searchStr)(item)}</li>;
        })}
      </ul>
    </form>
  )
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多