为什么推荐
最近工作上总是有让我很头疼的问题,需要让我显示一个报表单,并且还可以下载成为 PDF。简单来说,就是要实现在线预览和下载功能。正好以前看到过 react-pdf
这个插件,这次正好用上了。
前端生成 PDF 并且能动态渲染的插件其实非常少见。像 canvas + html2pdf
这种方式,生成的其实是图片格式的 PDF,无法编辑,且存在像素模糊的问题。而 react-pdf
可以真正地渲染出可编辑的 PDF 文件。
插件介绍
官网 : react-pdf
react-pdf
允许我们使用 React 组件的方式来构建 PDF 文档。它基于 @react-pdf/renderer
库,可以直接在浏览器端生成 PDF,并支持动态内容更新。
插件安装
# npm
npm install @react-pdf/renderer --save
# yarn
yarn add @react-pdf/renderer
# pnpm
pnpm add @react-pdf/renderer
# bun
bun install @react-pdf/renderer
基本使用
首先,我们需要引入 react-pdf
提供的核心组件:
import React from "react";
import { Document, Page, Text, View, StyleSheet, PDFDownloadLink, PDFViewer, Font } from "@react-pdf/renderer";
// @ts-ignore
import MK from '@/assets/font/MK.ttf';
// Register font
Font.register({ family: 'pinru', src: MK });
const data = [
{ id: 1, name: '张三', age: 20, score: 85 },
{ id: 2, name: '李四', age: 22, score: 90 },
{ id: 2, name: '李四', age: 22, score: 90 },
{ id: 2, name: '李四', age: 22, score: 90 },
{ id: 2, name: '李四', age: 22, score: 90 },
{ id: 2, name: '李四', age: 22, score: 90 },
];
// 定义样式
const styles = StyleSheet.create({
page: {
fontFamily: 'pinru',
fontSize: 10,
padding: 20,
lineHeight: 2,
},
header: { textAlign: 'center', fontSize: 18, marginBottom: 10 },
table: { display: 'table', width: '100%', borderStyle: 'solid', borderWidth: 1, borderColor: '#000' },
tableRow: { flexDirection: 'row' },
tableColHeader: { width: '25%', borderStyle: 'solid', borderWidth: 1, backgroundColor: '#eee', padding: 5, textAlign: 'center' },
tableCol: { width: '25%', borderStyle: 'solid', borderWidth: 1, padding: 5, textAlign: 'center' },
});
const MyDocument = () => (
<PDFViewer width="100%" height="100%">
<Document>
<Page size="A4" style={styles.page}>
<Text style={styles.header}>报表单</Text>
<View style={styles.table}>
{/* 表头 */}
<View style={styles.tableRow}>
<Text style={styles.tableColHeader}>ID</Text>
<Text style={styles.tableColHeader}>姓名</Text>
<Text style={styles.tableColHeader}>年龄</Text>
<Text style={styles.tableColHeader}>成绩</Text>
</View>
{/* 数据行 */}
{data.map((item, index) => (
<View style={styles.tableRow} key={index}>
<Text style={styles.tableCol}>{item.id}</Text>
<Text style={styles.tableCol}>{item.name}</Text>
<Text style={styles.tableCol}>{item.age}</Text>
<Text style={styles.tableCol}>{item.score}</Text>
</View>
))}
</View>
</Page>
</Document>
</PDFViewer>
);
const App = () => (
<div className="h-screen w-screen">
<h2>React PDF 示例</h2>
<MyDocument />
</div>
);
export default App;
演示效果
代码解析
Document
:表示 PDF 文档的根组件。Page
:定义 PDF 的页面,可以包含多个Page
。Text
:用于添加文本内容。View
:类似于div
,用于布局。StyleSheet.create
:用于定义 PDF 组件的样式。PDFDownloadLink
:提供 PDF 下载功能。
进阶使用
1. 生成多页 PDF
如果需要创建多页 PDF,可以这样实现:
const MultiPageDocument = () => (
<Document>
{[1, 2, 3].map((pageNum) => (
<Page key={pageNum} size="A4" style={styles.page}>
<View style={styles.section}>
<Text>第 {pageNum} 页</Text>
</View>
</Page>
))}
</Document>
);
2. 在页面中直接渲染 PDF 预览
react-pdf
还提供了 PDFViewer
组件,可以直接在页面中预览 PDF:
import { PDFViewer } from "@react-pdf/renderer";
const PDFPreview = () => (
<PDFViewer width="100%" height="500px">
<MyDocument />
</PDFViewer>
);
3. 处理复杂的报表
对于包含表格的 PDF,可以使用 react-pdf-table
或者手动布局:
<View style={{ flexDirection: "row", borderBottom: "1pt solid #000" }}>
<Text style={{ flex: 1 }}>列 1</Text>
<Text style={{ flex: 1 }}>列 2</Text>
<Text style={{ flex: 1 }}>列 3</Text>
</View>
总结
react-pdf
是一个非常强大的 PDF 生成工具,可以帮助前端开发者以组件化的方式构建 PDF 文档。它解决了传统 html2canvas
方式存在的模糊问题,并提供了丰富的自定义能力。
适用于:
- 动态生成 PDF 文档
- 在线预览和下载
- 生成多页 PDF
- 复杂的表格、报表