使用 React-pdf 在 React 中生成 Pdf 文档
这篇文章最初发表在我的博客上,查看更多内容。
简介
我最近在做一个项目,我有一个独特的(对我来说)要求,需要我从浏览器中的一组值生成 pdf 文件,通常在我的软件开发经验很少的情况下,使用在后端生成 pdf 文件用于节点 js 的 Puppeteer和用于 PHP 等的FPDF。所以我不得不寻找一个适用于我的用例的 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下载链接
-
BlobProvider
您可以查看文档以获取有关上述每个组件功能的更多详细信息,基本上这些组件可帮助您使用 JSXesques 语法创建 pdf。
造型
现在我们已经了解了如何创建 PDF 文档,我们如何设置它的样式?React-pdf使用 StyleSheet API 提供强大的样式解决方案,帮助您使用 CSS、媒体查询和 Flexbox 设置文档样式。检查他们支持的 CSS 属性的文档。
如果你是 CSS-in-JS 的忠实粉丝怎么办?好吧,它们还支持整个styled-componentsAPI。
字体
React-Pdf 有一个FontAPI,可帮助您从不同来源加载字体并在 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/>,它是我们应用程序的父组件。
电影列表.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组件包含此应用程序中的大部分逻辑。我们从@react-pdf/renderer导入PDFDownloadLink,这基本上是一个锚标签,使我们能够生成和下载 PDF 文档。PDFDownloadLink接受document道具,这是我们将很快使用本文前面列出的一些 React-primitives 创建的 PDF 模板。它还接受一个filename属性,可用于定义 PDF 文档的文件名,一个style属性为链接标签添加内联样式,一个className属性(如果您更喜欢使用类来设置样式)和children属性(锚标签内容) .
电影.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-primitives(VIEW, DOCUMENT) 和样式来定义 PDF 的结构。所以我将简要谈谈我在这里使用的一些 React-pdf API。
-
StyleSheet.create():它可以帮助您定义要在文档中使用的样式,它接受一个包含您要在文档中使用的所有 CSS 的对象,并返回一个您可以通过style应用于任何 PDF 元素的对象支柱。 -
Document:PDFDownloadLink``document属性仅接受Document类型的组件,因此在创建 PDF 模板时它必须是组件的根,并且只接受Page类型的子组件,Document只是 PDF 模板的包装器,它接受一些可选道具 -
Page:这表示文档中有一个页面,一个文档中可以有多个Pages。它接受一些道具来定义页面的size,orientation或者如果你想要页面换行wrap。道具 -
View:我想将此组件与 HTMLdiv进行比较,它可以帮助您分割或分割文档。道具 -
Text:该组件用于在文档上显示文本并对其应用样式。道具 -
Image: 该组件用于在文档上显示图像(网络或本地),这些图像可以是 PNG、JPG 或 base64。
演示应用
结论
在我使用这个库之前,我从未想过可以在客户端生成 PDF,react-pdf 不仅允许您这样做,而且还可以使用 JSXesque 语法来构建和设计 PDF 文档。我知道这个演示很简单,但我认为这个库在某些用例中可能很有用。
更多推荐
所有评论(0)