gpt4 book ai didi

reactjs - 如何用 React 组件替换 Markdown 渲染的 HTML 标签?

转载 作者:行者123 更新时间:2023-12-05 07:38:06 26 4
gpt4 key购买 nike

目前,我正在使用 marked 将 Markdown 转换为 HTML 代码,然后用 React 元素替换其中的一些部分。这导致 HTML 字符串和 React 元素的数组,它确实可以被渲染:

const prepareGuide = markdown => replaceToArray(
marked(markdown),
/<a href="SOME_SPECIAL_HREF".*?>(.*?)<\/a>/,
(match, label, slug) => <a href={`/${slug}`}>{label}</a>
)

const Guide = ({ guide }) =>
prepareGuide(guide.fields.text).map(
n => typeof n === 'object'
? n
: <span dangerouslySetInnerHTML={{ __html: n }} />
)

这个问题,让我们称之为解决方法,是每一段 HTML 都需要一个包装元素,比如 span(并使用 dangerouslySetInnerHTML)。

我基本上需要的是能够用 React 组件替换呈现的 HTML 元素,以添加 React 功能,如路由器链接和其他自定义元素。

还有其他方法吗?

编辑:replaceToArray我使用的函数类似于 String.prototype.replace,但返回一个数组(因此可以返回任何类型)

编辑:我采用的另一种方法是将 HTML 直接呈现给 DOM(使用 dangerouslySetInnerHTML),并使用容器元素的 ref 来查询我想要的所有元素代替。但是,下一个问题:要在我拥有的 HTML ref 中呈现 React 组件,我需要另一个 React root,这是可能的,但不切实际,因为我会丢失所有上下文(比如 Router),所以我什至不能以这种方式正确使用路由器链接。

最佳答案

我能够按如下方式解决这个问题:

我一直使用markeddangerouslySetInnerHTML 来直接设置HTML。现在,如第二种方法中所述,我使用 ref 查询要替换的元素。现在为了能够将 React 元素渲染到 HTML,我只使用了 ReactDOM.render 函数。

最大的问题是组件无法访问应用程序的上下文,因为我现在有多个 React 根。为了解决这个问题,我发现我们可以将上下文从一个组件复制到另一个组件:Is it possible to pass context into a component instantiated with ReactDOM.render?

因此,为了能够访问呈现 HTML 的组件中的上下文,我们需要为我们需要复制的上下文设置组件的 contextTypes

class Article extends Component {
static contextTypes = {
router: PropTypes.any
}

static propTypes = {
markdown: PropTypes.string
}

prepare(ref) {
const Provider = createContextProvider(this.context)
const links = Array.from(ref.querySelectorAll('a'))

links.forEach((link) => {
const span = document.createElement('span')
const { pathname } = url.parse(link.href)
const text = link.innerText

link.parentNode.replaceChild(span, link)
ReactDOM.render(
<Provider>
<Link to={pathname}>{text}</Link>
</Provider>,
span
)
})
}

render() {
return (
<article
ref={this.prepare}
dangerouslySetInnerHTML={{ __html: marked(this.props.markdown) }}
/>
)
}
}

上面的代码需要我从上面链接的问题中复制的片段。我称为 prepare 的方法用 React 根替换了特定的 HTML 节点。

function createContextProvider(context) {
class ContextProvider extends React.Component {
getChildContext() {
return context
}

render = () => this.props.children

static propTypes = { children: PropTypes.node }
}

ContextProvider.childContextTypes = {}
Object.keys(context).forEach(key => {
ContextProvider.childContextTypes[key] = PropTypes.any.isRequired
})

return ContextProvider
}

所以我们基本上有一个创建 Provider 组件的函数。该函数需要能够动态适应所需的上下文类型,这就是循环将它们设置为必需的原因。

关于reactjs - 如何用 React 组件替换 Markdown 渲染的 HTML 标签?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48140505/

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