0

Выделение текста с помощью ReactJS

15

Я пытаюсь выделить текст, соответствующий запросу, но не могу понять, как сделать так, чтобы теги отображались как HTML, а не как текст.

Вот мой код на React:

var Component = React.createClass({
    _highlightQuery: function(name, query) {
        var regex = new RegExp("(" + query + ")", "gi");
        return name.replace(regex, "<strong>$1</strong>");
    },
    render: function() {
        var name = "Javascript";
        var query = "java"
        return (
            <div>
                <input type="checkbox" /> {this._highlightQuery(name, query)}
            </div>
        );
    }
});

Текущий вывод: &lt;strong&gt;Java&lt;/strong&gt;script

Желаемый вывод: <strong>Java</strong>script

Как я могу отобразить теги как HTML?

5 ответ(ов)

1

Вот мой простой вспомогательный метод на два строчки:

getHighlightedText(text, highlight) {
    // Разделяем текст по ключевому слову, включая его в части, игнорируя регистр
    const parts = text.split(new RegExp(`(${highlight})`, 'gi'));
    return <span>{parts.map(part => part.toLowerCase() === highlight.toLowerCase() ? <b>{part}</b> : part)}</span>;
}

Этот метод возвращает элемент <span>, в котором запрашиваемые части выделены с помощью тегов <b> </b>. При необходимости его можно легко изменить для использования другого тега.

UPDATE: Чтобы избежать предупреждения о наличии уникального ключа, вот решение, основанное на <span> и установке свойства fontWeight для совпадающих частей:

getHighlightedText(text, highlight) {
    // Разделяем по ключевому слову и включаем его в части, игнорируя регистр
    const parts = text.split(new RegExp(`(${highlight})`, 'gi'));
    return <span>{parts.map((part, i) => 
        <span key={i} style={part.toLowerCase() === highlight.toLowerCase() ? { fontWeight: 'bold' } : {}}>
            {part}
        </span>)
    }</span>;
}

Теперь метод корректно обрабатывает уникальные ключи, что устраняет предупреждения.

0

Вот пример компонента React, который использует стандартный тег <mark> для выделения текста:

const Highlighted = ({text = '', highlight = ''}) => {
   if (!highlight.trim()) {
     return <span>{text}</span>;
   }
   const regex = new RegExp(`(${_.escapeRegExp(highlight)})`, 'gi');
   const parts = text.split(regex);
   return (
     <span>
        {parts.filter(part => part).map((part, i) => (
            regex.test(part) ? <mark key={i}>{part}</mark> : <span key={i}>{part}</span>
        ))}
    </span>
   );
};

А вот как его использовать:

<Highlighted text="the quick brown fox jumps over the lazy dog" highlight="fox"/>

Этот компонент принимает два пропса: text (текст для выделения) и highlight (слово или фраза для поиска). Если highlight пустой, компонент просто возвращает текст без изменений. В противном случае, он использует регулярное выражение для разделения текста на части и выделения совпадений с помощью тега <mark>.

0

По умолчанию ReactJS экранирует HTML для предотвращения XSS-атак. Если вам необходимо установить HTML, вам нужно использовать специальный атрибут dangerouslySetInnerHTML.

Попробуйте следующий код:

render: function() {
        var name = "Javascript";
        var query = "java"
        return (
            <div>
                <input type="checkbox" /> <span dangerouslySetInnerHTML={{__html: this._highlightQuery(name, query)}}></span>
            </div>
        );
    }

Обратите внимание, что использование dangerouslySetInnerHTML подразумевает определенные риски, связанные с безопасностью, поэтому убедитесь, что вводимые данные безопасны и не содержат вредоносного кода.

0

Ваш код создает компонент Highlight, который выделяет в тексте совпадения с искомым словом. Давайте разберем его по частям.

  1. Функция escapeRegExp: Эта функция принимает строку и экранирует специальные символы регулярных выражений. Это необходимо, чтобы избежать неожиданных результатов при создании регулярного выражения. Функция использует метод replace, чтобы заменить все специальные символы на экранированные версии.

    const escapeRegExp = (str = '') => (
      str.replace(/([.?*+^$[\]\\(){}|-])/g, '\\$1')
    );
    
  2. Компонент Highlight: Этот компонент принимает два пропса: search — строку для поиска и children — текст, в котором будет осуществляться поиск.

    • Создается регулярное выражение patt, которое нежно различает регистры и ищет искомую строку.
    • Текст разбивается на части с использованием метода split, который делит его на массив строк по найденному шаблону.
    • Если строка для поиска не пуста (search), каждая часть проверяется на совпадение с шаблоном. Если совпадение найдено, часть оборачивается в тег <mark>, что выделяет её на странице. В противном случае возвращается просто текстовая часть.
    const Highlight = ({ search = '', children = '' }) => {
      const patt = new RegExp(`(${escapeRegExp(search)})`, 'i');
      const parts = String(children).split(patt);
    
      if (search) {
        return parts.map((part, index) => (
          patt.test(part) ? <mark key={index}>{part}</mark> : part
        ));
      } else {
        return children;
      }
    };
    
  3. Использование компонента: В примере использования вы передаете строку "la" для поиска в тексте "La La Land". Компонент выделит все вхождения искомой строки, что, в данном случае, приведет к тому, что буквы "La" будут выделены.

    <Highlight search="la">La La Land</Highlight>
    

Таким образом, данный компонент удобен для выделения искомых фрагментов текста в пользовательском интерфейсе. Вы можете настраивать его для различных строк и контента.

0

С помощью react-mark.js вы можете просто использовать следующий код:

<Marker mark="hello">
  Hello World
</Marker>

Дополнительные ссылки:

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь