Javascript 用React中的Gallery替换img标签
渲染库组件存在问题: 我从服务器上获取带有html的字符串Javascript 用React中的Gallery替换img标签,javascript,html,reactjs,Javascript,Html,Reactjs,渲染库组件存在问题: 我从服务器上获取带有html的字符串 let serverResponse = ` <h3>Some title</h3> <p>Some text</p> <p> <img src=""> <img src=""> <img src=""> <br> <
let serverResponse = `
<h3>Some title</h3>
<p>Some text</p>
<p>
<img src="">
<img src="">
<img src="">
<br>
</p>
...
`
但当我得到2个或更多重复的
标记时,我想用组件替换它们。
我该怎么做?我试着用Regex
来做这件事,并用
来代替它们,但它不起作用。我想我需要在标记数组中拆分字符串,然后用
组件替换图像。
我试着用renderToString
...
getGallery = images => {
// Loop throw images and get sources
let sources = [];
if (images) {
images.map(img => {
let separatedImages = img.match(/<img (.*?)>/g);
separatedImages.map(item => sources.push(...item.match(/(https?:\/\/.*\.(?:png|jpg))/)));
});
}
if (sources.length) {
return <Gallery items={sources}>
}
return <div/>
};
...
<div dangerouslySetInnerHTML={{__html: serverResponse.replace(/(<img (.*?)>){2,}/g,
renderToString(this.getGallery(serverResponse.match(/(<img (.*?)>){2,}/g))))}}/>}
。。。
getGallery=图像=>{
//循环抛出图像并获取源
让源=[];
如果(图像){
images.map(img=>{
让separatedImages=img.match(//g);
separatedImages.map(item=>sources.push(…item.match(/(https?:\/\/.*。(?:png|jpg))/);
});
}
if(源.长度){
返回
}
返回
};
...
}
这不起作用,因为我得到的只是没有逻辑的html:(TLDR:您可以使用或类似的库 虽然JSX看起来非常相似,但它会被解析成一堆
React.createElement
,因此将React组件插入HTML字符串将不起作用。renderToString
也不起作用,因为它用于服务器端呈现React页面,在您的情况下不起作用
要用React组件替换HTML标记,您需要一个解析器来解析HTML字符串到节点,将节点映射到React元素并呈现它们。幸运的是,有一些库可以做到这一点,例如。首先,
危险的setinenerHTML
不是办法,您无法将gallery插入到Ini中你需要做的是多步骤的过程
1.将HTML解析为文档。在此阶段,您将把字符串转换为有效的DOM文档。使用DOMParser很容易做到这一点:
function getDOM (html) {
const parser = new DOMParser()
const doc = parser.parseFromString(`<div class="container">${html}</div>`, 'text/html')
return doc.querySelector('.container')
}
这就足够从DOM中创建JSX了。它可以这样使用:
const JSX = getJSX(getDOM(htmlString))
import React from 'react'
import { func, string } from 'prop-types'
function getDOM (html) {
const parser = new DOMParser()
const doc = parser.parseFromString(`<div class="container">${html}</div>`, 'text/html')
return doc.querySelector('.container')
}
function getJSX(root, injectGallery) {
return [...root.children].map(element => {
let children
if (element.querySelector('img + img') && injectGallery) {
const imageSources = [...element.querySelectorAll('img')].map(img => img.src)
children = injectGallery(imageSources)
} else {
children = element.children.length ? getJSX(element) : element.textContent
}
const props = [...element.attributes].reduce((prev, curr) => ({
...prev,
[curr.name]: curr.value
}), {})
return React.createElement(element.tagName, props, children)
})
}
const HTMLContent = ({ content, injectGallery }) => getJSX(getDOM(content), injectGallery)
HTMLContent.propTypes = {
content: string.isRequired,
injectGallery: func.isRequired,
}
export default HTMLContent
3.Inject Gallery。现在,如果元素
包含超过1个图像标记,您可以改进JSX创建,将Gallery注入到已创建的JSX中。我会将Inject函数作为第二个参数传递到getJSX
。与上述版本的唯一区别是在Gallery情况下如何计算子对象
:
if (element.querySelector('img + img') && injectGallery) {
const imageSources = [...element.querySelectorAll('img')].map(img => img.src)
children = injectGallery(imageSources)
} else {
children = element.children.length ? getJSX(element) : element.textContent
}
4.创建图库组件。现在是创建图库组件本身的时候了。该组件如下所示:
const JSX = getJSX(getDOM(htmlString))
import React from 'react'
import { func, string } from 'prop-types'
function getDOM (html) {
const parser = new DOMParser()
const doc = parser.parseFromString(`<div class="container">${html}</div>`, 'text/html')
return doc.querySelector('.container')
}
function getJSX(root, injectGallery) {
return [...root.children].map(element => {
let children
if (element.querySelector('img + img') && injectGallery) {
const imageSources = [...element.querySelectorAll('img')].map(img => img.src)
children = injectGallery(imageSources)
} else {
children = element.children.length ? getJSX(element) : element.textContent
}
const props = [...element.attributes].reduce((prev, curr) => ({
...prev,
[curr.name]: curr.value
}), {})
return React.createElement(element.tagName, props, children)
})
}
const HTMLContent = ({ content, injectGallery }) => getJSX(getDOM(content), injectGallery)
HTMLContent.propTypes = {
content: string.isRequired,
injectGallery: func.isRequired,
}
export default HTMLContent
从“React”导入React
从“属性类型”导入{func,string}
函数getDOM(html){
const parser=new DOMParser()
const doc=parser.parseFromString(`${html}`,'text/html')
return doc.querySelector(“.container”)
}
函数getJSX(根,注入库){
返回[…root.children].map(元素=>{
让孩子
if(element.querySelector('img+img')&&injectGallery){
const imageSources=[…element.querySelectorAll('img')].map(img=>img.src)
children=injectGallery(图像源)
}否则{
children=element.childrence.length?getJSX(element):element.textContent
}
常量属性=[…元素.属性].reduce((上一个,当前)=>({
…上一页,
[当前名称]:当前值
}), {})
return React.createElement(element.tagName、props、children)
})
}
constHtmlContent=({content,injectGallery})=>getJSX(getDOM(content),injectGallery)
HTMLContent.propTypes={
内容:string.isRequired,
注:需要功能,
}
导出默认HTMLContent
5.使用它!以下是您将如何一起使用:
<HTMLContent
content={serverResponse}
injectGallery={(images) => (
<Gallery images={images} />
)}
/>
(
)}
/>
下面是上述代码的演示
演示:解析当然是一种更好的方式。但是你能确切地告诉我你尝试了什么,以及它是如何不符合你的期望的吗?非常感谢!!!它在react 16上像一个符咒一样工作,但在react 15上不起作用。我在15.6.4上尝试过,但出现了一些问题。如果你能说,我必须做什么在react 15中进行更改。谢谢!您有任何错误吗?请在v15.x中尝试此版本