programing

리액트를 사용하여 텍스트 강조 표시JS

telecom 2023. 3. 31. 21:35
반응형

리액트를 사용하여 텍스트 강조 표시JS

쿼리와 일치하는 텍스트를 강조 표시하려고 하는데 태그가 텍스트가 아닌 HTML로 표시되는 방법을 알 수 없습니다.

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

현재 출력: <strong> Java </strong> 스크립트

원하는 출력: Javascript

간단한 Twoliner 도우미 방법은 다음과 같습니다.

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

이 강조 합니다.<b> </b>필요한 경우 다른 태그를 사용하도록 간단히 수정할 수 있습니다.

업데이트: 키 누락 경고를 피하기 위해 부품에 맞는 글꼴 무게 스타일 설정과 스팬에 기반한 솔루션을 다음에 제시합니다.

getHighlightedText(text, highlight) {
    // Split on highlight term and include term into parts, ignore case
    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>;
}

입니다.<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"/>

NPM에는 이미 원하는 작업을 수행할 수 있는 반응 컴포넌트가 있습니다.

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

제 해결책은 이렇습니다.

퍼포먼스에 했기 리액트 등)은 .dangerouslySetInnerHTML.

이 은 후속 를 단일 합니다.<span/>용장 스팬을 회피합니다.

const Highlighter = ({children, highlight}) => {
  if (!highlight) return children;
  const regexp = new RegExp(highlight, 'g');
  const matches = children.match(regexp);
  console.log(matches, parts);
  var parts = children.split(new RegExp(`${highlight.replace()}`, 'g'));

  for (var i = 0; i < parts.length; i++) {
    if (i !== parts.length - 1) {
      let match = matches[i];
      // While the next part is an empty string, merge the corresponding match with the current
      // match into a single <span/> to avoid consequent spans with nothing between them.
      while(parts[i + 1] === '') {
        match += matches[++i];
      }

      parts[i] = (
        <React.Fragment key={i}>
          {parts[i]}<span className="highlighted">{match}</span>
        </React.Fragment>
      );
    }
  }
  return <div className="highlighter">{parts}</div>;
};

사용방법:

<Highlighter highlight='text'>Some text to be highlighted</Highlighter>

코드펜에서 실제 예를 확인하십시오.

으로는 리액트 JS는 XSS를합니다.JS 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>
        );
    }
  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>

★★★★★★★★★★★★★★★★ react-mark.js을 사용하다

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

링크:

  • NPM : https://www.npmjs.com/package/react-mark.js
  • 문서: https://stackblitz.com/edit/react-mark-js?file=src/App.js

https://codesandbox.io/s/pensive-diffie-nwwxe?file=/src/App.js 함수로 일치 표시

import React from "react";

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      res: "Lorem ipsum dolor"
    };
    this.markMatches = this.markMatches.bind(this);
  }
  markMatches(ev) {
    let res = "Lorem ipsum dolor";
    const req = ev.target.value;
    if (req) {
      const normReq = req
        .toLowerCase()
        .replace(/\s+/g, " ")
        .trim()
        .split(" ")
        .sort((a, b) => b.length - a.length);
      res = res.replace(
        new RegExp(`(${normReq.join("|")})`, "gi"),
        match => "<mark>" + match + "</mark>"
      );
    }
    this.setState({
      res: res
    });
  }

  render() {
    return (
      <div className="App">
        <input type="text" onChange={this.markMatches} />
        <br />
        <p dangerouslySetInnerHTML={{ __html: this.state.res }} />
      </div>
    );
  }
}

export default App;

@Henok T의 솔루션에 근거해, 이하가 있습니다. lodash.

Typescript에 구현되어 Styled-components를 사용하지만, 유형을 삭제하고 스타일을 인라인으로 추가하는 것만으로 바닐라 JS에 쉽게 적응할 수 있습니다.

import React, { useMemo } from "react";
import styled from "styled-components";

const MarkedText = styled.mark`
  background-color: #ffd580;
`;

interface IHighlighted { 
  text?: string;
  search?: string;
}

export default function Highlighted({ text = "", search = "" }: IHighlighted): JSX.Element {
  /**
   * The brackets around the re variable keeps it in the array when splitting and does not affect testing
   * @example 'react'.split(/(ac)/gi) => ['re', 'ac', 't']
   */
  const re = useMemo(() => {
    const SPECIAL_CHAR_RE = /([.?*+^$[\]\\(){}|-])/g;
    const escapedSearch = search.replace(SPECIAL_CHAR_RE, "\\$1");
    return new RegExp(`(${escapedSearch})`, "i");
  }, [search]);

  return (
    <span>
      {search === ""
        ? text
        : text
            .split(re)
            .filter((part) => part !== "")
            .map((part, i) => (re.test(part) ? <MarkedText key={part + i}>{part}</MarkedText> : part))}
    </span>
  );
}
const highlightMatchingText = (text, matchingText) => {
  const matchRegex = RegExp(matchingText, 'ig');

  // Matches array needed to maintain the correct letter casing
  const matches = [...text.matchAll(matchRegex)];

  return text
    .split(matchRegex)
    .map((nonBoldText, index, arr) => (
      <React.Fragment key={index}>
        {nonBoldText}
        {index + 1 !== arr.length && <mark>{matches[index]}</mark>}
      </React.Fragment>
  ));
};

사용방법:

<p>highlightMatchingText('text here', 'text')</p>

또는

<YourComponent text={highlightMatchingText('text here', 'text')}/>

이 조작은 유효합니다.

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

하는 것입니다.if the, 진 the를 .<span>를 달다render() 더 기능하다_highlightQuery() 하나, 하나, 하나, 하나, 둘, 셋.

다른 접근 방식을 사용할 것을 제안합니다.컴포넌트를 . 를 들어 1개의 컴포넌트를 만듭니다.<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()방법.각 아이는 새 쿼리를 새 소품으로 수신하고 쿼리와 일치하는 부분을 강조 표시하여 텍스트를 출력합니다.

HTML 태그를 포함한 코멘트를 검색해야 했습니다.

예: 제 코멘트 중 하나는 다음과 같습니다.

헬로 월드

<div>Hello<strong>World</strong></div>

그래서 저는 이런 댓글들을 검색해서 검색 결과를 부각시키고 싶었어요.

아시다시피 HTML 태그를 사용하여 텍스트를 강조 표시할 수 있습니다.<mark>

그래서 저는 도우미 기능을 하나 만들어서 추가 작업을 수행했습니다.<mark>검색된 텍스트가 포함된 경우 텍스트에 태그를 지정합니다.

getHighlightedText = (text, highlight) => {
    if (!highlight.trim()) {
      return text;
    }
    const regex = new RegExp(`(${highlight})`, "gi");
    const parts = text.split(regex);
    const updatedParts = parts
      .filter((part) => part)
      .map((part, i) =>
        regex.test(part) ? <mark key={i}>{part}</mark> : part
      );
    let newText = "";
    [...updatedParts].map(
      (parts) =>
        (newText =
          newText +
          (typeof parts === "object"
            ? `<${parts["type"]}>${highlight}</${parts["type"]}>`
            : parts))
    );
    return newText;
  };

그래서 함수 안에서 텍스트와 검색 텍스트를 인수로 전달해야 합니다.

입력

getHighlightedText("<div>Hello<strong>World</strong></div>", "hello")

산출량

<div><mark>Hello</mark><strong>World</strong></div>

솔루션에 대해 더 많은 도움이 필요하면 알려주세요.

공백으로 분할된 여러 텍스트 부분을 강조 표시할 수 있도록 위에서 @Henok T 버전을 확장했지만 따옴표 또는 큰따옴표로 묶은 문자열은 함께 보관합니다.

예를 들어 하이라이트text "some text" 'some other text' text2다음 텍스트를 강조 표시합니다.

text some text some other text text2를 참조해 주세요.

 const Highlighted = ({text = '', highlight = ''}: { text: string; highlight: string; }) => {
    if (!highlight.trim()) {
        return <span>{text}</span>
    }
  
    var highlightRegex = /'([^']*)'|"([^"]*)"|(\S+)/gi;  // search for all strings but keep strings with "" or '' together
    var highlightArray = (highlight.match(highlightRegex) || []).map(m => m.replace(highlightRegex, '$1$2$3'));

    // join the escaped parts with | to a string
    const regexpPart= highlightArray.map((a) => `${_.escapeRegExp(a)}`).join('|');
    
    // add the regular expression
    const regex = new RegExp(`(${regexpPart})`, '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>
    )
}

언급URL : https://stackoverflow.com/questions/29652862/highlight-text-using-reactjs

반응형