React PDF在 React 中生成 PDF 文档 使用 React-pdf
这篇文章最初发表在我的博客上,请查看更多内容。
介绍
我最近在做一个项目,我有一个独特的(对我来说)要求,需要我从浏览器中的值数组中生成 pdf 文件,通常根据我在软件开发方面的一点经验,pdf 文件是在后端使用Puppeteer (node js) 和FPDF (PHP) 等生成的,所以我不得不寻找一个可以适合我的用例的 React 库,幸运的是我找到了React-pdf。我还找到了其他库,比如@progress/kendo-react-pdf,但我决定使用React-pdf,因为它的文档对开发人员友好。该库由Diego Muracciole
构建并由他维护。因此,在本教程/博客文章中,我将尝试简要解释 react-pdf 的工作原理,并引导您了解如何从来自Moviedb Api 的 对象数组生成 PDf 。
特征
当我尝试为我的用例选择合适的库时,我浏览了文档,React-pdf的一些功能让我决定使用它,我将简要地讨论一下它们:
成分
React-Pdf 使用React-Primitives规范来创建自定义组件,您可以使用这些组件来创建和构建 PDF 文档。
这些组件包括:
- 文档
- 页
- 看法
- 图像
- 文本
- 关联
- 笔记
- 帆布
- PDF查看器
- PDF下载链接
- Blob 提供程序
您可以查看文档以获取有关上述每个组件功能的更多详细信息,基本上这些组件可帮助您使用 JSXesques 语法创建 pdf。
造型
现在我们已经了解了如何创建 PDF 文档,那么该如何设置它的样式呢?React-pdf使用 StyleSheet API 提供了强大的样式解决方案,它可以帮助您使用 CSS、媒体查询和 Flexbox 来设置文档的样式。请查看文档了解它们支持的 CSS 属性。
如果您是 CSS-in-JS 的忠实粉丝怎么办?它们还支持完整的styled-components API。
字体
React-Pdf 有一个Font
API,可以帮助您从不同来源加载字体并在 PDF 文档中使用。
这些功能让我选择了 React-pdf。此外,我查看了Github 仓库,发现维护者Diego Muracciole非常活跃,并且会尽力回复大多数已提交的问题。
演示
我将简要地向您介绍一个使用 MoviesDB API 生成 PDF 的简单示例。这个演示将演示如何生成年度最佳影片。
文件夹结构
project
│ package.json
│
│
└───Public
│ │ 150.png
│ │ index.html
│ │ star.png
│
│
│
└───src
│ Movie.jsx
│ MovieList.jsx
| constant.js
| index.js
| styles.css
index.js(条目)
import React from "react";
import ReactDOM from "react-dom";
import MovieList from "./MovieList";
import "./styles.css";
function App() {
return (
<div className="App">
<MovieList />
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
index.js 是应用程序的入口点。它渲染了<MovieList/>
应用程序的父组件。
MovieList.jsx
import React, { useState } from "react";
import Axios from "axios";
import { PDFDownloadLink } from "@react-pdf/renderer";
import { API_KEY } from "./constants";
import { PdfDocument } from "./Movie";
const years = [
{ value: "2010", text: "2010" },
{ value: "2011", text: "2011" },
{ value: "2012", text: "2012" },
{ value: "2013", text: "2013" },
{ value: "2014", text: "2014" },
{ value: "2015", text: "2015" },
{ value: "2016", text: "2016" },
{ value: "2017", text: "2017" },
{ value: "2018", text: "2018" },
{ value: "2019", text: "2019" }
];
export default function MovieList() {
const [year, setYear] = useState("");
const [movieDetails, setDetails] = useState([]);
const [show, setHide] = useState(false)
const fetchMovie = async e => {
setYear(e.target.value);
try {
let res = await Axios(
`https://api.themoviedb.org/3/discover/movie?api_key=${API_KEY}&primary_release_year=${year}&sort_by=vote_average.desc`
);
setDetails(res.data.results);
setHide(true)
} catch (error) {
console.log(error);
}
};
return (
<div className="container">
<h2>Best movies of the year</h2>
<label htmlFor="movies">Select Year</label>
<select id="movies" className="select" onChange={fetchMovie}>
<option defaultValue="" disabled>
Select your option
</option>
{years.map((year, index) => {
return (
<option key={index} value={year.value}>
{year.text}
</option>
);
})}
</select>
{show &&<PDFDownloadLink
document={<PdfDocument data={movieDetails} />}
fileName="movielist.pdf"
style={{
textDecoration: "none",
padding: "10px",
color: "#4a4a4a",
backgroundColor: "#f2f2f2",
border: "1px solid #4a4a4a"
}}
>
{({ blob, url, loading, error }) =>
loading ? "Loading document..." : "Download Pdf"
}
</PDFDownloadLink>}
</div>
);
}
该MovieList.jsx
组件包含此应用程序中的大部分逻辑。我们PDFDownloadLink
从导入@react-pdf/renderer
,这基本上是一个锚标签,使我们能够生成和下载 PDF 文档。PDFDownloadLink
它接受一个document
props,这些 props 是我们即将使用本文前面列出的一些 React 原语创建的 PDF 模板。它还接受一个filename
可用于定义 PDF 文档文件名的 props、一个style
用于向链接标签添加内联样式的 props、一个className
如果您喜欢使用类来设置样式的 props,以及children
一个用于锚标签内容的 props。
Movie.jsx
import React from "react";
import {
Page,
Text,
View,
Document,
StyleSheet,
Image
} from "@react-pdf/renderer";
import moment from "moment";
const POSTER_PATH = "https://image.tmdb.org/t/p/w154";
const styles = StyleSheet.create({
page: {
backgroundColor: "#ffffff"
},
section: {
margin: 10,
padding: 10,
flexGrow: 1
},
movieContainer: {
backgroundColor: "#f6f6f5",
display: "flex",
flexDirection: "row",
padding: 5
},
movieDetails: {
display: "flex",
marginLeft: 5
},
movieTitle: {
fontSize: 15,
marginBottom: 10
},
movieOverview: {
fontSize: 10
},
image: {
height: 200,
width: 150
},
subtitle: {
display: "flex",
justifyContent: "space-between",
flexDirection: "row",
width: 150,
alignItems: "center",
marginBottom: 12
},
vote: {
display: "flex",
flexDirection: "row"
},
rating: {
height: 10,
width: 10
},
vote_text: {
fontSize: 10
},
vote_pop: {
fontSize: 10,
padding: 2,
backgroundColor: "#61C74F",
color: "#fff"
},
vote_pop_text: {
fontSize: 10,
marginLeft: 4
},
overviewContainer: {
minHeight: 110
},
detailsFooter: {
display: "flex",
flexDirection: "row"
},
lang: {
fontSize: 8,
fontWeight: 700
},
vote_average: {
fontSize: 8,
marginLeft: 4,
fontWeight: "bold"
}
});
export function PdfDocument(props) {
console.log("pdf props", props.data);
return (
<Document>
<Page style={styles.page}>
{props.data
? props.data.map((a, index) => {
return (
<View key={index} style={styles.movieContainer}>
<Image
style={styles.image}
source={
a.poster_path !== null
? `${POSTER_PATH}${a.poster_path}`
: "150.jpg"
}
/>
<View style={styles.movieDetails}>
<Text style={styles.movieTitle}>{a.title}</Text>
<View style={styles.subtitle}>
<View style={styles.vote}>
<Image source="star.png" style={styles.rating} />
<Text style={styles.vote_text}>{a.vote_count}</Text>
</View>
<View style={styles.vote}>
<Text style={styles.vote_pop}>{a.popularity}</Text>
<Text style={styles.vote_pop_text}>Popularity</Text>
</View>
</View>
<View style={styles.overviewContainer}>
<Text style={styles.movieOverview}>{a.overview}</Text>
</View>
<View style={styles.detailsFooter}>
<Text style={styles.lang}>
Language: {a.original_language.toUpperCase()}
</Text>
<Text style={styles.vote_average}>
Average Votes: {a.vote_average}
</Text>
<Text style={styles.vote_average}>
Release Date:{" "}
{moment(a.release_date, "YYYY-MM-DD").format(
" MMMM D Y"
)}
</Text>
</View>
</View>
</View>
);
})
: ""}
</Page>
</Document>
);
}
此Movie.jsx
组件是我们要生成的 PDF 的模板,我们在这里使用 React 基元(VIEW、DOCUMENT)定义 PDF 的结构以及样式。因此,我将简要介绍一下我在这里使用的一些 React-pdf API。
-
StyleSheet.create()
:它可以帮助您定义要在文档中使用的样式,它接受一个包含要在文档中使用的所有 CSS 的对象,并返回一个您可以通过style
prop 应用于任何 PDF 元素的对象。 -
Document
:该PDFDownloadLink
document
prop 仅接受类型的组件Document
,因此在创建 PDF 模板时,这必须是组件的根,并且仅接受类型的子项Page
,它Document
只是 PDF 模板的包装器,它接受一些可选的props -
Page
:这表示文档中的一个页面,Pages
一个文档中可以有多个页面。它接受一些属性来定义size
页面,orientation
或者用于页面换行wrap
。 -
View
:我想将这个组件与 HTML 进行比较div
,它可以帮助您分段或划分文档。道具 -
Text
:该组件用于在文档上显示文本并对其应用样式。道具 -
Image
:该组件用于在文档上显示图像(网络或本地),这些图像可以是PNG,JPG或base64。
演示应用程序
结论
在使用这个库之前,我从未想过可以在客户端生成 PDF。React-pdf 不仅能帮你做到这一点,还能让你使用 JSXesque 语法来构建和设计 PDF 文档。我知道这个演示很简单,但我认为这个库在某些用例中可能会有用。
文章来源:https://dev.to/finallynero/generate-pdf-documents-in-react-using-react-pdf-4ka7