如何同时呈现文本和组件

时间:2015-05-14 14:37:58

标签: javascript reactjs

我试图写一个反应组件来获取任何文本字符串,匹配:url,电子邮件,提及,标签并返回Btn组件而不是它们。有一段代码:

var StringParser = React.createClass({
  getDefaultProps: function() {
    return {
      type: 'div'
    }
  }

  , callbackMention: function(username) {
    console.log('Mention is ' + username)
  } 

  , callbackTag: function(tag) {
    console.log('Tag is ' + tag)
  } 

  , render: function() {
    var self = this
    var str = self.props.text
    var re = [
      "\\b((?:https?|ftp)://[^\\s\"'<>]+)\\b",
      "\\b(www\\.[^\\s\"'<>]+)\\b",
      "\\b(\\w[\\w.+-]*@[\\w.-]+\\.[a-z]{2,6})\\b", 
      "#([a-z0-9]+)",
      "@([a-z0-9]+)"]
    re = new RegExp(re.join('|'), "gi") 
    var parse = str.replace(re, function(parsed, url, www, email, tag, username){
      if(url && self.props.url) return ( <Btn callback={self.callbackTag} text={url}/> )
      if(www && self.props.url) return ( <Btn callback={self.callbackTag} text={www}/> )
      if(email && self.props.email) return ( <Btn callback={self.callbackTag} text={email}/> )
      if(tag && self.props.tag) return ( <Btn callback={self.callbackTag} text={tag}/> )
      if(username && self.props.username) return ( <Btn callback={self.callbackMention} text={username}/> )
      return parsed
    })
    console.log(parse)
    return React.createElement(self.props.type, self.props, parse)
  }
})

但是当我尝试解析这样的行时:

 <StringParser className="stringy" text={'hello www.bar.com#123 mail me at foo@d.com twitler me #123 @user123'}/>

我明白了:

hello [object Object] mail me at [object Object] twitler me [object Object] [object Object]

我有两种方法可以解决问题:

  1. 而不是Btn组件返回&span; class class =&#34; ...&#34;的onClick =&#34; this.callbackTag&#34;&GT; ...&#39;

  2. 将对象转换为字符串。怎么样?

  3. 如何解决这个问题?

2 个答案:

答案 0 :(得分:2)

String.prototype.replace()强制从给定的replacer函数返回到String的任何内容(因此你看到<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>),但是你想保留你正在创建的React组件作为要渲染的对象通过React。

你可以编写自己的replace函数,它返回一个Array而不是String:

'[object Object]'

然后这应该有效:

function replaceToArray(text, re, replacer, thisArg) {
  var lastIndex = 0
  var match
  var result = []

  while ((match = re.exec(text)) !== null) {
    // Text preceding the match
    if (lastIndex !== match.index) {
      result.push(text.slice(lastIndex, match.index))
    }
    result.push(replacer.apply(thisArg, match))
    lastIndex = re.lastIndex
  }
  // Text following the last match
  if (lastIndex !== text.length - 1) {
    result.push(text.slice(lastIndex))
  }

  return result
}

注意:由于您要返回包含组件的数组,如果React没有可用于在后续渲染中识别它们的唯一var parse = replaceToArray(str, re, function(parsed, url, www, email, tag, username) { if (url && this.props.url) return <Btn callback={this.callbackTag} text={url}/> if (www && this.props.url) return <Btn callback={this.callbackTag} text={www}/> if (email && this.props.email) return <Btn callback={this.callbackTag} text={email}/> if (tag && this.props.tag) return <Btn callback={this.callbackTag} text={tag}/> if (username && this.props.username) return <Btn callback={this.callbackMention} text={username}/> return parsed }, this) 道具,它会抱怨,如果你想让这个警告静音,你需要在你正在生成的组件中提供一个。

答案 1 :(得分:0)

要将它们转换为可以使用renderToString或renderToStaticMarkup的字符串,但您可能会失去回调功能。这就是react-intl处理html in strings

的方式