2015-04-15 3 views
4

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

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

Выходной ток: < сильный > Java </сильный > сценарий

Желаемая Выход: Java скрипт

ответ

10

Вот мой простой метод twoliner помощник:

getHighlightedText(text, higlight) { 
    // Split text on higlight term, include term itself into parts, ignore case 
    var parts = text.split(new RegExp(`(${higlight})`, 'gi')); 
    return <span>{parts.map(part => part.toLowerCase() === higlight.toLowerCase() ? <b>{part}</b> : part)}</span>; 
} 

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

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

getHighlightedText(text, higlight) { 
    // Split on higlight term and include term into parts, ignore case 
    let parts = text.split(new RegExp(`(${higlight})`, 'gi')); 
    return <span> { parts.map((part, i) => 
     <span key={i} style={part.toLowerCase() === higlight.toLowerCase() ? { fontWeight: 'bold' } : {} }> 
      { part } 
     </span>) 
    } </span>; 
} 
+0

Этот учебник может помочь кому-то тоже: https://www.vladopandzic.com/react/creating-react-highlighter-component/ –

3

По умолчанию 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> 
     ); 
    } 
+1

Есть ли лучший способ сделать это без использования dangerouslySetInnerHTML атрибута? Спасибо –

+3

Да, есть. Для этого потребуется создать новый компонент React, который обрабатывает «выделение» запроса. Затем вы можете использовать этот компонент внутри этого. Этот подход был бы более в духе ReactJS, где вещи разбиты на небольшие компоненты, каждый из которых делает 1 вещь и делает это действительно хорошо. Это [принцип единой ответственности] (http://en.wikipedia.org/wiki/Single_responsibility_principle), и это относится и к другим областям программирования. –

-1

Это должно работать:

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

В основном вы генерируя реагировать компонент на лету. Если вы хотите, вы можете поместить тег <span> внутри функции render(), а не _highlightQuery().

0

Я предлагаю вам использовать другой подход. Создайте один компонент, скажем <TextContainer />, который содержит <Text /> элементов.

var React = require('react'); 
var Text = require('Text.jsx'); 

var TextContainer = React.createClass({ 
    getInitialState: function() { 
     return { 
      query: '' 
     }; 
    }, 
    render: function() { 
     var names = this.props.names.map(function (name) { 
      return <Text name={name} query={this.state.query} /> 
     }); 
     return (
      <div> 
       {names} 
      </div> 
     ); 
    } 
}); 

module.exports = TextContainer; 

Как вы видите, текстовый контейнер хранит как состояние текущий запрос. Теперь <Text /> компонент может быть что-то вроде этого:

var React = require('react'); 

var Text = React.createClass({ 
    propTypes: { 
     name: React.PropTypes.string.isRequired, 
     query: React.PropTypes.string.isRequired 
    }, 

    render: function() { 
     var query = this.props.query; 
     var regex = new RegExp("(" + query + ")", "gi"); 
     var name = this.props.name; 
     var parts = name.split(regex); 
     var result = name; 

     if (parts) { 
      if (parts.length === 2) { 
       result = 
        <span>{parts[0]}<strong>{query}</strong>{parts[1]}</span>; 
      } else { 
       if (name.search(regex) === 0) { 
        result = <span><strong>{query}</strong>{parts[0]}</span> 
       } else { 
        result = <span>{query}<strong>{parts[0]}</strong></span> 
       } 
      } 
     } 

     return <span>{result}</span>; 
    } 

}); 

module.exports = Text; 

Таким образом, корневой компонент имеет в состоянии, текущий запрос. Когда его состояние будет изменено, оно вызовет метод детей render(). Каждый ребенок получит новый запрос в качестве новой опоры и выведет текст, выделив те части, которые будут соответствовать запросу.

2

Существует уже react component on NPM делать то, что вы хотите:

var Highlight = require('react-highlighter'); 
[...] 
<Highlight search={regex}>{name}</Highlight> 
0

Вот пример среагировать компонента, который использует стандартный <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"/> 
0
const escapeRegExp = (str = '') => (
    str.replace(/([.?*+^$[\]\\(){}|-])/g, '\\$1') 
); 

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

    <Highlight search="la">La La Land</Highlight> 
Смежные вопросы