使用react-to-print和html2pdf导出React组件时生成空白PDF
问题:使用react-to-print和html2pdf生成的PDF为空白文件
在React项目中结合react-to-print与html2pdf库实现组件打印及PDF导出功能,参照示例编写代码后,生成的PDF文件为空白,但控制台输出的HTML元素包含所需内容。
相关代码
导出逻辑代码
const handleDownload = useReactToPrint({ onPrintError: (error) => console.log(error), content: () => componentRef.current, removeAfterPrint: true, print: async (printIframe) => { const doc = printIframe.contentDocument; console.log(doc); if (doc) { const html = doc.getElementsByTagName("html")[0]; console.log(html); const exporter = new Html2Pdf(html,{filename:"Note.pdf"}); await exporter.getPdf(true); } }, });
引用的组件
<DesignPrintNote ref={componentRef} conSello={conSello} conFecha={conFecha} tienda={tienda} fechavalue={fechavalue} contenido={contenido}/>
组件DOM结构
return ( <div className='print-hojaVacaciones' ref={ref}> <div className="printChild printFuturaFont"> <img id="logotipo" src={header}/> <div className="parrafo"> <div style={{display: "flex", alignItems: "center"}} > {conFecha && <div id="conjuntofecha" style={{display: "flex", alignItems: "center"}}> {tienda}, a {moment({fechavalue}).format("DD/MM/YYYY")} </div>} <div style={{display: "flex", justifyContent: "center", alignItems: "center", marginLeft: "10px"}}> <div style={{display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center"}}></div> </div> </div> <div style={{display:"flex", flexDirection:"row", alignItems: "center"}} className="form-check form-switch show2hidden"></div> <p id="parrafoprint" className="zona_escritura" style={{border:"none"}} contentEditable="true"></p> <div style={{margin:"1cm 1cm 0 0",display:"flex",justifyContent:"space-between"}}> <span>Atentamente,</span> {conSello && <img id="sello" src={sello} style={{width:"4.5cm", alignSelf:"flex-end"}}/>} </div> </div> </div> </div>)
可能的问题及解决方法
iframe内容未完全加载
react-to-print创建的iframe可能还没完全渲染内容就被html2pdf抓取了。可以在print回调中加入等待逻辑,确保内容加载完成:print: async (printIframe) => { await new Promise(resolve => { if (printIframe.contentDocument.readyState === 'complete') { resolve(); } else { printIframe.onload = resolve; } }); const doc = printIframe.contentDocument; // 后续PDF生成代码不变 }绕开react-to-print的iframe直接生成
不需要通过react-to-print的iframe中转,直接使用组件的DOM节点生成PDF:const handleDownload = async () => { const exporter = new Html2Pdf(componentRef.current, {filename:"Note.pdf"}); await exporter.getPdf(true); };样式未正确注入iframe
react-to-print可能遗漏部分组件样式,可手动将所需样式添加到iframe中:print: async (printIframe) => { const doc = printIframe.contentDocument; const styleTag = doc.createElement('style'); styleTag.textContent = ` .print-hojaVacaciones { width: 100%; } .printChild { padding: 1cm; } .printFuturaFont { font-family: 你的字体; } /* 其他组件依赖的样式 */ `; doc.head.appendChild(styleTag); // 后续PDF生成代码不变 }contentEditable元素内容未同步
组件中的<p contentEditable="true">内容可能未被正确捕获,可在生成PDF前将其内容复制到一个静态元素中,再传入html2pdf:const handleDownload = async () => { const tempElement = document.createElement('div'); tempElement.innerHTML = componentRef.current.innerHTML; // 替换contentEditable元素为静态内容 const editableP = tempElement.querySelector('#parrafoprint'); if (editableP) { const staticP = document.createElement('p'); staticP.textContent = editableP.textContent; editableP.replaceWith(staticP); } const exporter = new Html2Pdf(tempElement, {filename:"Note.pdf"}); await exporter.getPdf(true); };
内容的提问来源于stack exchange,提问作者Germán
相关产品推荐
相关产品推荐

