Javascript 使用ReactJS突出显示文本

Javascript 使用ReactJS突出显示文本,javascript,reactjs,react-jsx,Javascript,Reactjs,React Jsx,我试图突出显示与查询匹配的文本,但我不知道如何将标记显示为HTML而不是文本 var Component = React.createClass({ _highlightQuery: function(name, query) { var regex = new RegExp("(" + query + ")", "gi"); return name.replace(regex, "<strong>$1</strong>");

我试图突出显示与查询匹配的文本,但我不知道如何将标记显示为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>
        );
    }
});
var Component=React.createClass({
_highlightQuery:函数(名称、查询){
var regex=new RegExp(“(“+query+”),“gi”);
返回名称。替换(regex,“$1”;
},
render:function(){
var name=“Javascript”;
var query=“java”
返回(
{this.\u highlightQuery(名称,查询)}
);
}
});
当前输出:Java脚本


所需输出:Javascript

默认情况下,js转义HTML以防止XSS。如果您确实希望设置HTML,则需要使用特殊属性
危险设置HTML
。 请尝试以下代码:

render: function() {
        var name = "Javascript";
        var query = "java"
        return (
            <div>
                <input type="checkbox" /> <span dangerouslySetInnerHTML={{__html: this._highlightQuery(name, query)}}></span>
            </div>
        );
    }
render:function(){
var name=“Javascript”;
var query=“java”
返回(
);
}
这应该可以:

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>
        );
    }
});
var Component=React.createClass({
_highlightQuery:函数(名称、查询){
var regex=new RegExp(“(“+query+”),“gi”);
返回“+name.replace(正则表达式“$1”)+”;
},
render:function(){
var name=“Javascript”;
var query=“java”
返回(
{jsxttransformer.exec(this.\u highlightQuery(name,query))}
);
}
});

基本上,您正在动态生成一个react组件。如果需要,可以将
标记放在
render()
函数中,而不是放在
\u highlightQuery()
函数中。

我建议您使用不同的方法。创建一个组件,例如
,它包含
元素

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;
var React=require('React');
var Text=require('Text.jsx');
var TextContainer=React.createClass({
getInitialState:函数(){
返回{
查询:“”
};
},
render:function(){
var names=this.props.names.map(函数(名称){
返回
});
返回(
{names}
);
}
});
module.exports=TextContainer;
如您所见,文本容器保存为当前查询的状态。现在,
组件可以是这样的:

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;
var React=require('React');
var Text=React.createClass({
道具类型:{
名称:React.PropTypes.string.isRequired,
查询: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结果=名称;
如有(部分){
如果(parts.length==2){
结果=
{parts[0]}{query}{parts[1]};
}否则{
if(name.search(regex)==0){
结果={query}{parts[0]}
}否则{
结果={query}{parts[0]}
}
}
}
返回{result};
}
});
module.exports=文本;

因此,根组件的状态为当前查询。当其状态将被更改时,它将触发子级的
render()
方法。每个孩子都将收到新的查询作为一个新的道具,并输出文本,突出显示与查询匹配的部分。

下面是我的简单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>;
}
getHighlightedText(文本,高亮显示){
//在突出显示术语上拆分文本,将术语本身包含为多个部分,忽略大小写
const parts=text.split(新的RegExp(`(${highlight})`,'gi');
返回{parts.map(part=>part.toLowerCase()===highlight.toLowerCase()?{part}:part)};
}
它返回一个span,其中请求的零件用
标记突出显示。如果需要,可以简单地修改它以使用另一个标记

更新:为避免出现唯一的键丢失警告,以下是一个基于跨度和设置匹配零件的fontWeight样式的解决方案:

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>;
}
getHighlightedText(文本,高亮显示){
//在高亮显示项上拆分,并将项包含到各个部分中,忽略大小写
const parts=text.split(新的RegExp(`(${highlight})`,'gi');
返回{parts.map((part,i)=>
{part}
)
} ;
}
已经有了一个方法来做你想做的事情:

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

以下是一个react组件示例,该组件使用标准的
标记突出显示文本:

const Highlighted=({text='',highlight=''})=>{
如果(!highlight.trim()){
返回{text}
}
const regex=new RegExp(`(${escapeRegExp(highlight)})`,'gi')
const parts=text.split(正则表达式)
返回(
{parts.filter(part=>part.map)((part,i)=>(
regex.test(part){part}:{part}
))}
)
}
下面是如何使用它

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

const escapeRegExp=(str='')=>(
str.replace(/([.?*+^$[\]\\(){}\\-])/g,“\\$1”)
);
常量突出显示=({search='',children=''})=>{
const patt=newregexp(`(${escapeRegExp(search)})`i');
常量部分=字符串(子项)。拆分(子项);
如果(搜索){
返回parts.map((part,index)=>(
零件试验(零件){零件}:零件
));
}否则{
返回儿童;
}
};
拉兰
这是我的解决方案

我试图将重点放在简单性和性能上,因此我避免了在React之外手动操作DOM的解决方案,或者像
DangerlySetinerHTML
这样的不安全方法

此外,此解决方案负责将后续匹配合并到单个
,从而避免出现冗余范围

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