You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将react-bootstrap表格导出为PDF?useReactToPrint无效求替代方案

适配React-Bootstrap表格的PDF导出方案

如果useReactToPrint结合useRef的方案无法正常工作,可以试试以下三种替代方案,覆盖不同场景需求:


方法1:jsPDF + html2canvas 捕获DOM生成PDF

该方案通过将React-Bootstrap表格的DOM节点转为图片,再插入PDF,能最大程度保留原表格样式,适合需要快速复用现有UI的场景。

步骤

  1. 安装依赖:
npm install jspdf html2canvas
  1. 代码实现:
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质量更高,适合需要深度集成的场景。

步骤

  1. 安装依赖:
npm install @react-pdf/renderer
  1. 代码实现:
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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 19:05:13