如何同时渲染文本和组件
How to render text and components at the same time
我正在尝试编写一个获取任何文本字符串的反应组件,匹配:url、电子邮件、提及、标签和 returns 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]
我有两种解决问题的方法:
代替Btn组件return'span class="..." onClick="this.callbackTag">...'
将对象转换为字符串。怎么样?
如何解决这个问题?
要将它们转换为字符串,您可以使用 renderToString, or renderToStaticMarkup, but you might lose the ability to callback. This is how react-intl handles html in strings
String.prototype.replace()
将您 return 从给定的替换函数强制转换为字符串(因此您看到的 '[object Object]'
),但您想保留您正在使用的 React 组件创建为 React 渲染的对象。
您可以编写自己的替换函数,其中 return 是一个数组而不是一个字符串:
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
}
那么这应该可行:
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)
注意: 因为你正在 return 中包含组件的数组,如果它们没有唯一值,React 会报错key
prop 它可以用来在后续渲染中识别它们,因此如果你想消除该警告,你需要在你生成的组件中提供一个。
我正在尝试编写一个获取任何文本字符串的反应组件,匹配:url、电子邮件、提及、标签和 returns 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]
我有两种解决问题的方法:
代替Btn组件return'span class="..." onClick="this.callbackTag">...'
将对象转换为字符串。怎么样?
如何解决这个问题?
要将它们转换为字符串,您可以使用 renderToString, or renderToStaticMarkup, but you might lose the ability to callback. This is how react-intl handles html in strings
String.prototype.replace()
将您 return 从给定的替换函数强制转换为字符串(因此您看到的 '[object Object]'
),但您想保留您正在使用的 React 组件创建为 React 渲染的对象。
您可以编写自己的替换函数,其中 return 是一个数组而不是一个字符串:
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
}
那么这应该可行:
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)
注意: 因为你正在 return 中包含组件的数组,如果它们没有唯一值,React 会报错key
prop 它可以用来在后续渲染中识别它们,因此如果你想消除该警告,你需要在你生成的组件中提供一个。