如何将react-bootstrap表格导出为PDF?useReactToPrint无效求替代方案
适配React-Bootstrap表格的PDF导出方案
如果useReactToPrint结合useRef的方案无法正常工作,可以试试以下三种替代方案,覆盖不同场景需求:
方法1:jsPDF + html2canvas 捕获DOM生成PDF
该方案通过将React-Bootstrap表格的DOM节点转为图片,再插入PDF,能最大程度保留原表格样式,适合需要快速复用现有UI的场景。
步骤
- 安装依赖:
npm install jspdf html2canvas
- 代码实现:
import React, { useRef } from 'react'; import { Table, Button } from 'react-bootstrap'; import jsPDF from 'jspdf'; import html2canvas from 'html2canvas'; const BootstrapTablePDF = () => { const tableRef = useRef(null); const exportToPDF = async () => { const tableElement = tableRef.current; if (!tableElement) return; // 捕获表格为canvas,提高清晰度并处理跨域 const canvas = await html2canvas(tableElement, { scale: 2, useCORS: true, logging: false }); // 转换为图片数据并初始化PDF const imgData = canvas.toDataURL('image/png'); const pdf = new jsPDF('p', 'mm', 'a4'); const pageWidth = pdf.internal.pageSize.getWidth(); const imgWidth = pageWidth - 20; // 左右留10mm边距 const imgHeight = (canvas.height * imgWidth) / canvas.width; let position = 10; // 顶部起始位置 let remainingHeight = imgHeight; // 处理长表格分页 pdf.addImage(imgData, 'PNG', 10, position, imgWidth, imgHeight); remainingHeight -= pdf.internal.pageSize.getHeight(); while (remainingHeight >= 0) { position = remainingHeight - imgHeight; pdf.addPage(); pdf.addImage(imgData, 'PNG', 10, position, imgWidth, imgHeight); remainingHeight -= pdf.internal.pageSize.getHeight(); } pdf.save('table.pdf'); }; return ( <div> <Button onClick={exportToPDF}>导出PDF</Button> <Table ref={tableRef} striped bordered hover> <thead> <tr> <th>#</th> <th>姓名</th> <th>年龄</th> <th>邮箱</th> </tr> </thead> <tbody> <tr> <td>1</td> <td>张三</td> <td>25</td> <td>zhangsan@example.com</td> </tr> <tr> <td>2</td> <td>李四</td> <td>30</td> <td>lisi@example.com</td> </tr> </tbody> </Table> </div> ); }; export default BootstrapTablePDF;
注意点
- 若样式丢失,可尝试给表格容器添加固定宽度,或在
html2canvas配置中加入allowTaint: true scale: 2用于避免PDF导出后模糊
方法2:jsPDF 手动构建PDF表格
完全脱离DOM,用jsPDF的API手动绘制表格,彻底规避DOM相关问题,适合数据结构简单、需要高度定制PDF布局的场景。
代码实现
import React from 'react'; import { Table, Button } from 'react-bootstrap'; import jsPDF from 'jspdf'; const BootstrapTablePDF = () => { const tableData = [ { id: 1, name: '张三', age: 25, email: 'zhangsan@example.com' }, { id: 2, name: '李四', age: 30, email: 'lisi@example.com' }, ]; const exportToPDF = () => { const pdf = new jsPDF('p', 'mm', 'a4'); const pageWidth = pdf.internal.pageSize.getWidth(); let currentY = 20; // 顶部起始位置 // 绘制表头 pdf.setFontSize(12); pdf.setFont('helvetica', 'bold'); pdf.text('#', 10, currentY); pdf.text('姓名', 30, currentY); pdf.text('年龄', 70, currentY); pdf.text('邮箱', 100, currentY); pdf.line(10, currentY + 2, pageWidth - 10, currentY + 2); currentY += 10; // 绘制数据行 pdf.setFont('helvetica', 'normal'); pdf.setFontSize(10); tableData.forEach(item => { // 分页判断(A4页面底部留30mm边距) if (currentY > 270) { pdf.addPage(); currentY = 20; // 重新绘制表头 pdf.setFontSize(12); pdf.setFont('helvetica', 'bold'); pdf.text('#', 10, currentY); pdf.text('姓名', 30, currentY); pdf.text('年龄', 70, currentY); pdf.text('邮箱', 100, currentY); pdf.line(10, currentY + 2, pageWidth - 10, currentY + 2); currentY += 10; pdf.setFont('helvetica', 'normal'); pdf.setFontSize(10); } pdf.text(item.id.toString(), 10, currentY); pdf.text(item.name, 30, currentY); pdf.text(item.age.toString(), 70, currentY); pdf.text(item.email, 100, currentY); currentY += 8; }); pdf.save('table.pdf'); }; return ( <div> <Button onClick={exportToPDF}>导出PDF</Button> <Table striped bordered hover> <thead> <tr> <th>#</th> <th>姓名</th> <th>年龄</th> <th>邮箱</th> </tr> </thead> <tbody> {tableData.map(item => ( <tr key={item.id}> <td>{item.id}</td> <td>{item.name}</td> <td>{item.age}</td> <td>{item.email}</td> </tr> ))} </tbody> </Table> </div> ); }; export default BootstrapTablePDF;
方法3:react-pdf 原生构建PDF文档
用React组件语法编写PDF内容,与现有React代码风格一致,生成的PDF质量更高,适合需要深度集成的场景。
步骤
- 安装依赖:
npm install @react-pdf/renderer
- 代码实现:
import React from 'react'; import { Table, Button } from 'react-bootstrap'; import { Document, Page, Text, View, StyleSheet, PDFDownloadLink } from '@react-pdf/renderer'; // 定义PDF样式 const styles = StyleSheet.create({ page: { padding: 20 }, table: { display: 'table', width: '100%', borderCollapse: 'collapse' }, tableRow: { flexDirection: 'row' }, tableHeader: { backgroundColor: '#f0f0f0', fontWeight: 'bold' }, tableCell: { border: '1px solid #ccc', padding: 8, fontSize: 10 } }); // PDF文档组件 const TablePDFDocument = ({ data }) => ( <Document> <Page size="A4" style={styles.page}> <View style={styles.table}> {/* 表头 */} <View style={[styles.tableRow, styles.tableHeader]}> <Text style={styles.tableCell}>#</Text> <Text style={styles.tableCell}>姓名</Text> <Text style={styles.tableCell}>年龄</Text> <Text style={styles.tableCell}>邮箱</Text> </View> {/* 数据行 */} {data.map(item => ( <View key={item.id} style={styles.tableRow}> <Text style={styles.tableCell}>{item.id}</Text> <Text style={styles.tableCell}>{item.name}</Text> <Text style={styles.tableCell}>{item.age}</Text> <Text style={styles.tableCell}>{item.email}</Text> </View> ))} </View> </Page> </Document> ); const BootstrapTablePDF = () => { const tableData = [ { id: 1, name: '张三', age: 25, email: 'zhangsan@example.com' }, { id: 2, name: '李四', age: 30, email: 'lisi@example.com' }, ]; return ( <div> <PDFDownloadLink document={<TablePDFDocument data={tableData} />} fileName="table.pdf" > {({ loading }) => loading ? '准备导出...' : <Button>导出PDF</Button>} </PDFDownloadLink> <Table striped bordered hover> <thead> <tr> <th>#</th> <th>姓名</th> <th>年龄</th> <th>邮箱</th> </tr> </thead> <tbody> {tableData.map(item => ( <tr key={item.id}> <td>{item.id}</td> <td>{item.name}</td> <td>{item.age}</td> <td>{item.email}</td> </tr> ))} </tbody> </Table> </div> ); }; export default BootstrapTablePDF;
内容的提问来源于stack exchange,提问作者Sinera Wijethunga
相关产品推荐
相关产品推荐

