gpt4 book ai didi

javascript - 在 React 中用 Gallery 替换 img 标签

转载 作者:行者123 更新时间:2023-11-30 20:45:57 25 4
gpt4 key购买 nike

渲染库组件有问题:我从服务器获取带有 html 的字符串

let serverResponse = `
<h3>Some title</h3>
<p>Some text</p>
<p>
<img src="">
<img src="">
<img src="">
<br>
</p>
...
`

现在我用 dangerouslySetInnerHTML 呈现这个响应

<div dangerouslySetInnerHTML={{ __html: serverResponse }} />

但是当我有 2 个或更多重复 <img>我想用组件替换它们的标签。我怎样才能做到这一点?我试着用 Regex 来做并将它们替换为 <Gallery/>但它不起作用。我认为我需要在标签数组中拆分字符串,然后用 <Gallery/> 替换图像成分。我试着用 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))))}}/>}

这行不通,因为我得到的只是没有逻辑的 html :(

最佳答案

首先,dangerouslySetInnerHTML 不是要走的路,您不能将图库插入其中并让 React 处理它。您需要做的是多步程序。

<强>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')
}

我使这个辅助函数返回带有您的 HTML 节点的容器。下一步将需要它。

<强>2。将 DOM 文档转换为 React JSX 树。 现在您有了 DOM 树,通过从相应的 DOM 节点创建单独的 React 元素,很容易将其转换为 JSX。此函数需要递归处理 DOM 树的所有级别。像这样的事情会做:

function getJSX(root) {
return [...root.children].map(element => {
const 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)
})
}

这足以从 DOM 中创建 JSX。它可以这样使用:

const JSX = getJSX(getDOM(htmlString))

<强>3。注入(inject)图库。现在,如果 element 包含超过 1 个图像标签,您可以改进 JSX 创建以将 Gallery 注入(inject)创建的 JSX。我会将注入(inject)函数作为第二个参数传递给 getJSX。与上述版本的唯一区别是 children 在 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。创建 Gallery 组件。 现在是创建 Gallery 组件本身的时候了。该组件将如下所示:

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

<强>5。使用它!以下是如何一起使用它们:

<HTMLContent
content={serverResponse}
injectGallery={(images) => (
<Gallery images={images} />
)}
/>

这是上面这段代码的演示。

演示: https://codesandbox.io/s/2w436j98n

关于javascript - 在 React 中用 Gallery 替换 img 标签,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48708305/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com