React:在动态加载的 HTML 中注入组件的最佳方法?

Posted

技术标签:

【中文标题】React:在动态加载的 HTML 中注入组件的最佳方法?【英文标题】:React : best way to inject Component in dynamically loaded HTML? 【发布时间】:2016-06-27 17:48:59 【问题描述】:

我是 React 的新手(我更容易使用 jQuery 或 AngularJS)。我有一个特殊情况,我没有找到解决它的好方法......

我的应用程序包含一个类似于“文档查看器”的区域。它从后端加载 html 内容(通过 API,使用 Fetch)并将其注入“查看器”组件。加载的 HTML 内容看起来像“大学报告”(它只是一个格式化文本,只有 <span><p> 带有 class="..." 属性,仅此而已)。 例如:<p>Lorem ispum <span>some text</span> loreb bis <span>ipsum</span></p> ...

我加载内容,并以这种方式将其注入我的组件 <Viewer>render() 中: <div dangerouslySetInnerHTML= getFreshlyLoadedHTML() />

简单,它工作得很好!

但是...现在,我想在加载的 HTML 中注入一些“交互式”组件。例如,提供反馈的按钮等。API 必须决定在格式化文本 (HTML) 的单词/节点之间放置组件的位置。 前任 : <p> Lorem ispum <span>some text</span> loreb bis <span>ipsum</span> <MyFeedbackButton paragraph="1.3"/> </p><p>Other Lorem Ipsum<p><span>...</span>

在那里,我被困住了,因为如果加载的 HTML 中有组件,我无法使用 dangerouslySetInnerHTML...

第一次尝试:我尝试修改 API,而不是将字符串中的 HTML 发送到应用程序,而是发送一个自定义 JSON 结构,该结构几乎代表了我想要的最终 JSX 结构。然后,在我的反应页面中,渲染函数只需要解析 JSON 并构建 JSX(如果不清楚,这里是一个 JsFiddle 示例:https://jsfiddle.net/damienfa/69z2wepo/34536/)

它有效,但我不敢相信这是个好方法......

我看到一个主要问题:我从渲染函数构建的所有 HTML 节点(跨度,p...)都被 reactJs 引用,真的有必要吗?大多数情况下,有“死”节点(我的意思是,永远不会改变的 dom 节点,这是静态格式的文本)。

看看那些永远不会交互的节点上的所有“data-reactid”......

您对此案有何建议?

我对 API 发送的 JSON 结构的尝试怎么样?

有没有办法说“不要引用那个元素”?

你清楚地看到我的问题的更好解决方案吗?

【问题讨论】:

我认为发送可以转换为 JSX 的 JSON 是一个明智的选择,您提到的该解决方案的主要问题实际上是 React 的一部分,我认为这实际上不是一个主要问题?除了一个非常小的性能问题,我认为这不会是一个大问题 我同意@Geraint,不用担心开销,它很可能可以忽略不计。但是是否需要将内容作为 HTML 获取,是否还需要在获取的内容之间添加按钮? 【参考方案1】:

您当前的工作流程不是很安全,并且容易出现许多潜在的错误和敞开的大门,尤其是在代码注入方面...

由于 react 跟踪节点导致的过载不是问题,React 可以跟踪 10 000 个节点并且没有问题(实际上在我的许多应用程序中,React 有超过 100 000 个节点需要关心,它仍然可以完美运行)。

我在这里看到了不同的解决方案:

    如果只有 3 或 4 种可能的动态组件和顺序,您可能有像“模板”这样的组件,您可以简单地向其发送文本参数。这是最安全、最简单的选择。 如果它不适合您的用例,但 JSON 文件只能包含一组有限的组件,则这些组件应位于您的主应用程序中,然后使用 JSON 中的自定义道具呈现。实际上,考虑到数据结构,您可以考虑使用 xml 而不是 json,并构建一个您将解析和呈现的 xml 树。只会呈现白名单中的组件,这将极大地限制潜在的安全问题。如果需要在 XML 解析器上做一些工作。 如果 JSON 文件可以包含许多不同且不可预测的组件,或者如果这些组件的行为在很大程度上是动态的并且独立于您的应用程序,您不妨考虑使用具有自己的 JS 和 HTML 的 iframe,这样部分代码与其余部分隔离。

【讨论】:

谢谢@Mijamo!确实,动态组件只有 2 种可能性,更多的是 '

' 和 &lt;span&gt; 节点。所以,我会考虑你的解决方案 1. 你看过我给的 JsFiddle 吗?您提出的解决方案有什么区别?关于第二个解决方案,我不确定为什么我需要使用 XML 代替?在前端 js 中解析 XML 是一件很痛苦的事情……(但我承认 XML 是我的数据结构更连贯的视图)。关于,代码注入,怎么可能?在我的 JsFiddle 中,我有一个小标签白名单,我建议“清理”字符串(删除链接等)。

【参考方案2】:

尝试使用 JSX 在 React 的内部内容中使用内联匿名函数。有用!请注意连接数据的方式,这样就没有用户可以从输入或文本字段注入 HTML 的路径。 &lt;div className="html-navigation-button">(() => const CreateMarkup = ( sNavItemName :string ) =&gt; return __html: sNavItemName ; var sTextToAddHtmlTo = props.nextNavItem.name.toString(); sTextToAddHtmlTo = sTextToAddHtmlTo.replace( "/", "/&lt;wbr&gt;" ); return ( <div dangerouslySetInnerHTML=CreateMarkup( sTextToAddHtmlTo ) &gt; </div&gt; ); )() </div>

我没有覆盖“render()”的 React 内部结构,而是仅使用带有 props 连接的 React 组件将数据传递给它以进行渲染。 我在 React 组件的返回内容中添加了 'dangerouslySetInnerHTML' 的钩子,因此没有简单的方法来拦截和操作它。 因此,没有 100% 的安全保证,但这就是为 Web 服务、数据库增加良好的安全性以及使用 CORS 和 CORB 有助于锁定安全风险的地方。

【讨论】:

以上是关于React:在动态加载的 HTML 中注入组件的最佳方法?的主要内容,如果未能解决你的问题,请参考以下文章

s-s-r:反应应用程序中的动态导入如何在客户端加载组件时处理html未匹配

React 路由动态加载

react 动态组件加载器

从外部源动态加载 React 组件/捆绑包

React 组件的动态加载

在js代码中怎样用react 加载组件