用React.js组件替换部分html字符串并渲染(不带dangerouslySetInnerHTML)
Replace part of html string with React.js component and render (without dangerouslySetInnerHTML)
我正在使用Node.js/React.js客户端从WordPress API获取数据,我面临着相当棘手的问题。但希望你能帮我!:)
所以我有这种数据作为一个字符串来自WordPress API(单页内容):
"<h1>Curabitur turpis.</h1>
<p>Vestibulum purus quam, scelerisque ut, mollis sed, nonummy id, metus. Praesent blandit laoreet nibh. Aenean commodo ligula eget dolor. Donec vitae sapien ut libero venenatis faucibus.</p>
[gravityform id=”42″ title=”true” description=”true”]
<h2>Donec vitae orci sed</h2>
<p><strong>Suspendisse faucibus</strong>, nunc et pellentesque egestas, lacus ante convallis tellus, vitae iaculis lacus elit id tortor. Vestibulum rutrum, mi nec elementum vehicula, eros quam gravida nisl, id fringilla neque ante vel mi.</p>
<blockquote><p>Nullam nulla eros, ultricies sit amet, nonummy id, imperdiet feugiat, pede. Aliquam lobortis. In turpis.</p></blockquote>
<ul><li>item</li><li>item</li><li>item</li></ul>"
我需要做的是将短代码[gravityform id=”42″ title=”true” description=”true”]
替换为React组件<GravityForm />
与想要的事件处理程序等,并呈现其他html元素。
我正在做这样的替换:
export const replaceGravityFormShortcode = html => {
if(!html) return html;
const gravityFormRegexp = /'[gravityform id=.([0-9]{1,}).*?']/g;
return replace(
html,
gravityFormRegexp,
function (fullMatch, id) {
return <GravityForm key={id} formId={id} />;
}
);
};
所以用React组件替换[shortcodes]已经覆盖了,但之后的html数据看起来像这样:
[
0:"<h1>Curabitur turpis.</h1><p>Vestibulum purus quam, scelerisque ut, mollis sed, nonummy id, metus. Praesent blandit laoreet nibh. Aenean commodo ligula eget dolor. Donec vitae sapien ut libero venenatis faucibus.</p>"
1:Object (GravityForm-component)
2:"<h2>Donec vitae orci sed</h2><p><strong>Suspendisse faucibus</strong>, nunc et pellentesque egestas, lacus ante convallis tellus, vitae iaculis lacus elit id tortor. Vestibulum rutrum, mi nec elementum vehicula, eros quam gravida nisl, id fringilla neque ante vel mi.</p><blockquote><p>Nullam nulla eros, ultricies sit amet, nonummy id, imperdiet feugiat, pede. Aliquam lobortis. In turpis.</p></blockquote><ul><li>item</li><li>item</li><li>item</li></ul>"
]
显然这在render()
中不起作用因为
- 如果我只渲染数据表单会正常工作但所有html字符串默认都是转义的
- 如果我使用
dangerouslySetInnerHTML
,它看起来像这样(<GravityForm />
是[object Object]
)
那么对于这个问题有什么合理的解决方案吗?或者应该从不同的角度来看待这个问题?
谢谢你的帮助!
编辑
是的,你的解决方案是将html字符串更改为React Components,但它仍然不能解决html转义问题。输出还是像(截图)<h1>Curabitur turpis.</h1><p>Vestibulum purus quam, scelerisque ut, mollis sed, nonummy id, metus. Praesent blandit laoreet nibh. Aenean commodo ligula eget dolor. Donec vitae sapien ut libero venenatis faucibus.</p>
<h2>Donec vitae orci sed</h2><p><strong>Suspendisse faucibus</strong>, nunc et pellentesque egestas, lacus ante convallis tellus, vitae iaculis lacus elit id tortor. Vestibulum rutrum, mi nec elementum vehicula, eros quam gravida nisl, id fringilla neque ante vel mi.</p><blockquote><p>Nullam nulla eros, ultricies sit amet, nonummy id, imperdiet feugiat, pede. Aliquam lobortis. In turpis.</p></blockquote><ul><li>item</li><li>item</li><li>item</li></ul>
但是,它甚至可能呈现的html没有解析html元素一个接一个从字符串?
EDIT 2 (Solution - kind of)
所以我终于找到了解决这个问题的方法。
- 我使用react-html-parser从数据字符串解析html元素
- 那么数据就像(对象是React元素):
[ 0:Object 1:Object 2:"[gravityform id=”42″ title=”true” description=”true”]" 3:Object 4:Object 5:Object 6:Object ]
- 最后循环数据
replaceGravityFormShortcodesFromArrayOfObjects(arrayOfObjects)
,用<GravityForm />
替换[gravityform id=”42″ title=”true” description=”true”]
,然后渲染数据
export const replaceGravityFormShortcodesFromArrayOfObjects =(dataArray) => {
if(!dataArray) return dataArray;
const gravityFormRegexp = /'[gravityform id=.([0-9]{1,}).*?']/g;
forEach(dataArray, (value, index) => {
if(typeof value === 'string'){
const temp = replace(
value,
gravityFormRegexp,
function (fullMatch, id) {
return <GravityForm key={id} formId={id} />;
}
);
if(temp.length === 1 && isObject(temp[0])){
dataArray = [
...dataArray.slice(0, index),
temp[0],
...dataArray.slice(index + 1),
];
}
}
}
return dataArray;
};
BUT这只适用于html结构是一层深度的情况。如果"[gravityform id=”42″ title=”true” description=”true”]"
是在React元素props.children
,它变得棘手,我还没有找到工作的解决方案。
我遇到了完全相同的问题,下面是我的解决方案:
定义字符串:const s = `<h1>Curabitur turpis.</h1>
<p>Vestibulum purus quam, scelerisque ut, mollis sed, nonummy id, metus. Praesent blandit laoreet nibh. Aenean commodo ligula eget dolor. Donec vitae sapien ut libero venenatis faucibus.</p>
[gravityform id=”42″ title=”true” description=”true”]
<h2>Donec vitae orci sed</h2>
<p><strong>Suspendisse faucibus</strong>, nunc et pellentesque egestas, lacus ante convallis tellus, vitae iaculis lacus elit id tortor. Vestibulum rutrum, mi nec elementum vehicula, eros quam gravida nisl, id fringilla neque ante vel mi.</p>
<blockquote><p>Nullam nulla eros, ultricies sit amet, nonummy id, imperdiet feugiat, pede. Aliquam lobortis. In turpis.</p></blockquote>
<ul><li>item</li><li>item</li><li>item</li></ul>`
按[*]
:
const normalText = s.split(/'[['s'S]+']/g)
提取id:
let ids = [];
const re = /'[gravityform id=.*([0-9]{1,}).*']/g;
s.replace(re, (fullMatch, id) => {
ids.push(id)
})
现在数组normalText
和ids
有我们想要连接的内容。只需将它们连接起来:
const output = normalText.map((text, index) => {
<div>
{text}
<GravityForm key={ids[index]} formId={ids[index]} />
</div>
})
// Then put `output` in the `render` function
您可能需要稍微调整一下正则表达式,因为您的字符串包含像”
这样的unicode。要么先删除它们,要么先转义它们。
为了不转义HTML:
<div dangerouslySetInnerHTML={{ __html: text }}/>
参考:https://facebook.github.io/react/docs/dom-elements.html
- 制作一个不带HTML a标记但在动画播放完毕后指向其他页面的超链接
- 使用不带文本文件的OpenLayers显示POI
- 获取用户选择的不带时区的日期
- 在web应用程序中的新搜索中重新加载搜索结果(不带jQuery)
- 不带jquery的全屏分页
- 用于匹配不带字符的单词的正则表达式
- 淡入不带HTML的背景图像
- ajax中的文本链接不带Jquery
- 重写不带defineProperty的对象getter
- 删除不带jQuery的覆盖css
- 返回并扔在一行上,不带分号
- 使用不带数组的 Javascript 快速声明一长串变量
- 舍入javascript字符串并显示不带小数的美元格式
- 键控特殊字符,如öüä激发2次并输出不带'¨'
- 将数据从html服务器(不带php)传递到带php的服务器,并将数据返回到该非php服务器
- 打开Chrome或Firefox,不带标签和其他菜单项,并设置屏幕位置和大小
- 文本区接收输入的URL值,并在文本区显示URL,不带代码(
- 用React.js组件替换部分html字符串并渲染(不带dangerouslySetInnerHTML)
- 使用不带ES6语法的梦魇.js并生成
- 如何正则表达式两个标记之间的字符串,并返回不带标记的字符串