javascript - 我可以从 HTML 字符串或 dom 节点/元素创建 React 元素吗
问题描述
我正在从 SharePoint 检索 HTML 字符串,需要解析和修改数据并构建要在我的反应应用程序中显示的反应元素。
基本上,我有代码(作为字符串)以类似于以下格式返回给我:
"
<div>
<div data-sp-canvasdataversion="1">This could be a header</div>
<div data-sp-canvasdataversion="1"><img src="titleimage.jpg"></div>
<div data-sp-canvasdataversion="1"><a href="pdfLink.pdf">This is a link to a PDF</a></div>
</div>
"
然后我需要循环遍历子元素并构建一个新的 React 元素,其中包含返回的部分内容和一些新部分,例如
<div>
<div data-sp-canvasdataversion="1">This could be a header</div>
<div data-sp-canvasdataversion="1"><img src="titleimage.jpg"></div>
<PDFViewer file={""pdfLink.pdf""}></PDFViewer>
</div>
我最初使用 dangerouslySetInnerHTML 来简单地显示数据,但现在我需要删除一大块 html,根据数据创建一个 react 元素并将新元素注入代码中。由于我现在正在尝试插入一个组件,所以 vanilla html 将不起作用。
我可以通过将子节点转换为 dom 节点来循环遍历子节点,但我不知道如何将 dom 节点或元素用作 React Element Child。
我试过了:
let element = React.createElement('div', {}, HTMLString);
let node = document.createRange().createContextualFragment(HTMLString).firstChild;
let element = React.createElement('div', {}, node);
let node = document.createRange().createContextualFragment(HTMLString).firstChild;
let node2 = document.createElement("div");
node2.appendChild(node);
node2 = node2.firstElementChild as HTMLDivElement;
let element = React.createElement('div', {}, node2);
没有根据需要工作,并给我错误Objects are not valid as a React child (found: [object HTMLDivElement]).
或类似的东西。
我需要的是这样的:
let element = React.createElement('div');
let node = document.createRange().createContextualFragment(HTMLString).firstChild;
node.childNodes.forEach(child => {
if(...//child IS NOT pdf)
element.appendChild(child)
else if(...//child IS pdf){
...
element.appendChild(<PDFViewer file="linktopdf.pdf">)
}
})
然后我希望能够在渲染中使用它
render {
...
return(
<div className="container">
{element}
</div>
);
}
请让我知道这是否可能以及如何。我能想到的唯一可能的解决方案是将子元素保存为字符串并使用 dangerouslySetInnerHTML 来生成所有它们,但我真的想摆脱使用 dangerouslySetInnerHTML,尤其是这样。
解决方案
我最终做了我不想做的事情,即使用危险的SetInnerHTML。如果有人提出更好的解决方案,请随时分享。
async getArticleComponents(data: any) {
if (!data)
return null;
let slides = []
let node = document.createRange().createContextualFragment(data).firstChild;
let children = node.childNodes;
for (let i = 0; i < children.length; i++) {
var element = (children[i] as HTMLDivElement);
var controlElement = element.attributes.getNamedItem("data-sp-controldata");
var jObj = controlElement ? JSON.parse(controlElement.value) : null;
if (jObj.controlType === 3) {
var childEle = element.firstElementChild;
var webPartData = childEle.attributes.getNamedItem("data-sp-webpartdata");
var wpJObj = webPartData ? JSON.parse(webPartData.value) : null;
if (wpJObj.title == "File viewer") {
let ext = (/.*\.(.*)/i).exec(wpJObj.properties.file)[1].toLowerCase();
if (ext === "pdf") {
var pdf = await fetch(`/api/SharePoint/GetFile?url=${encodeURIComponent(`${wpJObj.serverProcessedContent.links.serverRelativeUrl}`)}`)
.then(res => res.text())
.then(pdf => pdf ? `data:application/pdf;base64,${pdf}` : null);
slides.push(<PDFViewer key={jObj.id} file={{ pdf, fileName: "test" } as IPdfMeta} />);
}
} else
slides.push(<div key={jObj.id} dangerouslySetInnerHTML={{ __html: element.outerHTML }}></div>);
}
else if (jObj.controlType !== 0) {
slides.push(<div key={jObj.id} dangerouslySetInnerHTML={{ __html: element.outerHTML }}></div>);
}
}
return slides;
}
推荐阅读
- angular - 如何使用 Reactive Forms 从 Angular material-datepicker 中获取键盘输入的值?
- ruby-on-rails - Rails:Sass 找不到 node_modules
- mysql - TypeORM:如何查询多对多以及一对一/多
- tsql - 是否可以将一个视图列中的值用作第二个视图列中的条件?
- url - 在 Cypress 的 `route` 函数中获取匹配的 URL
- python - 尝试使用 values_list 获取字段值时出现 AttributeError
- r - 如何计算没有新客户的月份
- pandas - 如何对同一 DataFrame 中的两个自变量执行对数和线性回归
- c - 使用超出范围的索引访问全局数组变量时,始终将值打印为 0
- python - tensorflow/keras 中混合密度网络的形状不兼容问题