如何使用 React JS 创建 PDF?

发布:2024-10-18 14:40 阅读:51 点赞:0

介绍

有时,您需要将应用程序的表格或数据保存为 PDF 以便于共享。使用React PDF Renderer,您可以轻松地将 React 组件转换为高质量的 PDF。在本博客中,我们将学习如何轻松地将您的 Web 内容转换为可共享的 PDF。

React PDF Renderer 有自己的一组组件,与常规 React 组件或 HTML 标签略有不同。但是,它的功能很容易理解。一旦您掌握了基础知识,您将能够有效地使用 React PDF Renderer 在 React 应用中创建 PDF。在进入代码之前,我们首先来看看 React PDF Renderer 提供的主要组件,看看它们是如何工作的。

先决条件

  1. React 基础知识
  2. 您的计算机上安装了 Node.js 和 npm
  3. 熟悉 CSS
  4. 设置现有的 React 项目(我们将介绍这一点)

有了这些基础知识,您就可以开始将 React 组件转换为 PDF 的过程。

React PDF 渲染器组件

React PDF Renderer 使用各种组件来帮助您将 React 组件转换为 PDF。以下是关键组件及其用途:

  • 文档:创建 PDF 文档的根元素。
  • 页面:代表 PDF 中的单个页面。
  • 视图 (View ):类似于 HTML 中的容器元素div
  • 文本:用于呈现 PDF 中的文本。
  • 图像:允许您在 PDF 中包含图像。
  • 链接:启用 PDF 内的可点击链接。
  1. 查看组件

    • 用途:充当其他组件的容器,类似于
      HTML。
    • 样式格式:支持宽度、高度、边距、填充、背景颜色、边框等样式。
    
    <View style={{ width: 100, height: 50, backgroundColor: 'blue' }} >
    /* pdf content */
    </View>
    
    
  2. 文本组件

    • 用途:呈现 PDF 文档中的文本内容。
    • 样式格式:支持字体大小、字体系列、字体粗细、文本对齐方式、颜色和其他与文本相关的样式。
    
    <Text style={{ fontSize: 14, fontWeight: 'bold', color: 'black' }}>
    Hello, World!
    </Text>
    
    
  3. 图像组件

    • 用途:将图像嵌入PDF文档。
    • 样式格式:支持图像的宽度、高度和源 URL 等属性。
    <Image src="example.jpg" style={{ width: 200, height: 100 }} />
    
  4. 页面组件

    • 用途:定义 PDF 文档中的单独页面。
    • 样式格式:支持每页的大小、方向和边距等属性。
    <Page size="A4" style={{ margin: 10 }}>Page Content</Page>
    
  5. 链接组件

    • 用途:在 PDF 文档内创建超链接。
    • 样式格式:支持定义超链接的 URL 和样式选项。

    <Link src="https://example.com" style={{ color: 'blue' }}> Click here </Link>
  6. 文档组件

    • 用途:代表整个PDF文档。
    • 样式格式:支持全局文档设置,例如页面大小、边距和元数据。
    
    <Document title="Example Document">
    <Page>
      <Text>
          Content
      </Text>
    </Page>
    </Document>
    
    

这些是使用 React PDF 时使用的基本组件。您可以在此处查看具有可用有效 props 的完整组件列表。

设置环境

您可以在现有应用中开始构建 PDF,也可以使用专门用于 React PDF 的在线 REPL。在线 React PDF REPL 的优点是我们可以立即查看代码的预览。如果没有这个预览系统,我们每次都需要下载 PDF 才能查看。

因此,我们将使用 React PDF 的在线 REPL,因为它允许我们即时预览代码更改。创建 PDF 时,这个预览功能非常有用,因为它可以节省时间并帮助我们尽早发现错误。不过,我还将介绍如何在 React 应用程序中设置 React PDF。

让我们创建一个新的 React 应用程序,安装 React PDF Renderer,并用它编写第一行代码。

打开终端并运行以下命令,使用 Create React App 创建一个新的 React 应用程序

npx create-react-app my-react-pdf-app
 

此命令将创建一个名为 my-react-pdf-app 的新目录,其中包含基本的 React 设置。

cd my-react-pdf-app
 

使用 npm 安装 React PDF Renderer 库。

npm install @react-pdf/renderer
 

my-react-pdf-app在您最喜欢的代码编辑器(如 VSCode)中打开新创建的项目( )。MyDocument.jssrc目录中创建一个名为的新文件。

 
// src/MyDocument.js

import React from 'react';
import { Document, Page, Text, View, StyleSheet } from '@react-pdf/renderer';

// Create styles
const styles = StyleSheet.create({
  page: {
    flexDirection: 'column',
    backgroundColor: '#E4E4E4',
  },
  section: {
    margin: 10,
    padding: 10,
    flexGrow: 1,
  },
});

// Create Document Component
const MyDocument = () => (
  <Document>
    <Page size="A4" style={styles.page}>
      <View style={styles.section}>
        <Text>Section #1</Text>
      </View>
      <View style={styles.section}>
        <Text>Section #2</Text>
      </View>
    </Page>
  </Document>
);

export default MyDocument;

打开App.js并修改它以呈现 PDF 文档。

// src/App.js

import React from 'react';
import { PDFDownloadLink } from '@react-pdf/renderer';
import MyDocument from './MyDocument';

const App = () => (
  <div className="App">
    <header className="App-header">
      <PDFDownloadLink document={<MyDocument />} fileName="mypdf.pdf">
        {({ blob, url, loading, error }) =>
          loading ? 'Loading document...' : 'Download PDF now!'
        }
      </PDFDownloadLink>
    </header>
  </div>
);

export default App;
打开您的终端,确保您在项目目录中,然后启动开发服务器。
npm start

您的默认浏览器应该会自动打开并导航到http://localhost:3000,您将在那里看到下载 PDF 的链接。

本地主机预览

但在本博客中,我们将使用在线代码 REPL,以便我们可以立即看到输出。然后,我们可以在 React 应用程序中使用相同的代码来下载它。两种方法都会产生相同的结果。

代码 PDF

因此,我们将编写此 PDF 设计。通过此设计,我们将了解所有组件的工作原理。之后,您可以编写任何 PDF 设计。

我们将要创建的 PDF

所以,到目前为止,我们了解了 React PDF 有三个主要组件:

  • 文档
  • 看法

此PDF设计也分为这三个主要部分。

了解 pdf 组件

因此,从上图中,我希望您了解我们首先需要构建什么。首先,我们将使用组件创建一个文档。然后,我们将声明一个,之后,我们将声明一个并开始在那里定义我们的组件。

步骤:

基本设置
首先导入我们需要用于 React PDF 的基本内容和组件。

import React from 'react';
import { Page, Text, View, Document, StyleSheet, Image } from '@react-pdf/renderer';
 

文档样式
现在我们将设置文档样式。在这里,我们将设置整个文档的外观。我们将使用它StyleSheet.create来定义 PDF 组件的样式。这类似于 CSS,但以 JavaScript 对象编写:

const styles = StyleSheet.create({
  page: {
    padding: 20,
    backgroundColor: '#ffffff'
  },
  section: {
    marginBottom: 20
  }
});
// we will add more style later on.

在这里,我们将像这样在组件中使用页面和部分样式。

<Page style={styles.page}>

定义数据
定义您想要在 PDF 文档中显示的数据。此数据可以是动态的,可以从 API 或数据库中获取:

const data = [
  {
    title: 'Attack on Titan',
    studio: 'Wit Studio',
    genre: 'Action, Dark Fantasy',
    releaseDate: '04-07-2013',
    status: 'Completed',
    rating: '9.0',
    cost: '$120'
  }
];
 

创建文档组件
定义MyDocument将构造 PDF 文档的组件。名称可以是任何名称。它是我们的 React 组件。

const MyDocument = () => {
 return (
   // Our pdf code will be here
     );
};
export default MyDocument;
 

该组件返回描述 PDF 文档结构的 JSX。因此,在 return 语句中,我们将首先使用第一个 React PDF 组件。

const MyDocument = () => {
 return (
     
       /* Here we will steup our page */
     
     );
};
export default MyDocument;
 

这将创建一个黑色的 PDF 文档。

pdf 预览

创建 PDF 页面
现在,让我们开始为 PDF 创建页面。使用组件定义页面。组件的数量将决定页面的数量。例如,如果您使用两个标签,您的 PDF 将有两页。如果单个页面的数据太多,React PDF 将根据需要自动创建其他页面。

该组件有几个属性,例如size,它定义了页面大小,如 A4、A2、A3 等,以及许多其他属性。您可以在此处查看所有页面属性

道具页面

// Create Document Component
const MyDocument = () => {
  return (
    <Document>
      <Page size="A4" style={styles.page}>
        <View> 
          <Text>Hello</Text>
        </View>
      </Page>
    </Document>
  );
};
export default MyDocument;
 

在这里,我们使用<Page>组件并添加一个sizeprop,为其赋予一个值。我们还使用style样式对象中的定义。在<Page>组件内部,我们使用<View>组件,在其中,我们使用组件<Text>显示文本“Hello”。输出将如下所示:

pdf 第一个输出

因此,该View组件的工作原理与 类似div。例如,如果您希望将 PDF 中的大框划分为特定列,并希望为每列赋予不同的颜色,则只需要几个View组件和一些样式。如果您需要添加文本,请使用Text组件。要添加图像,请使用 组件Image。查看下面的代码和输出。

// Create styles
const styles = StyleSheet.create({
  page: {
    padding: 20,
    backgroundColor: '#ffffff'
  },
  section: {
    marginBottom: 20
  },
  bigBox: {
    flexDirection: 'row',
    marginBottom: 20,
    borderWidth: 1,
    borderColor: '#000',
  },
  column: {
    flex: 1,
    padding: 10,
    borderWidth: 1,
    borderColor: '#000',
  },
  column1: {
    backgroundColor: '#ffcccc',
  },
  column2: {
    backgroundColor: '#ccffcc',
  },
  column3: {
    backgroundColor: '#ccccff',
  },
  text: {
    fontSize: 12,
  },
  image: {
    width: "auto",
    height: 100,
  },
  canvas: {
    width: '100%',
    height: 100,
    borderWidth: 1,
    borderColor: '#000',
    backgroundColor: '#e0e0e0',
  }
});

// Create Document Component
const MyDocument = () => {
  return (
      <Document>
    <Page size="A4" style={styles.page}>
      <View style={[styles.bigBox]}>
        <View style={[styles.column, styles.column1]}>
          <Text style={styles.text}>This is a text column</Text>
        </View>
        <View style={[styles.column, styles.column2]}>
          <Image
            style={styles.image}
            src="https://t3.ftcdn.net/jpg/07/24/53/02/360_F_724530208_783brjeXb7pllU2HefNMxNc1TynemreM.jpg"
          />
        </View>
        <View style={[styles.column, styles.column3]}>
          <View style={styles.canvas}>
            <Text style={styles.text}>Canvas section (Placeholder)</Text>
          </View>
        </View>
      </View>
    </Page>
  </Document>
  );
};

export default MyDocument;
 

pdf 中更多颜色

解释

  • styles.bigBox:此样式定义包含三列的主容器。
  • styles.column:此样式定义每列的基本样式,包括填充和边框。
  • styles.column1,,styles.column2styles.column3这些样式定义每列的背景颜色。
  • styles.text:此样式用于第一列内的文本。
  • styles.image:此样式用于第二列里面的图像。
  • styles.canvas:此样式定义第三列内的占位符画布部分。

这里,为了实现视觉区分,每列都赋予了不同的背景颜色。第一列包含文本,第二列包含图像,第三列包含画布部分的占位符。

因此,为此,我们仅使用了ViewTextImage组件。我希望您现在明白,要创建任何组件,我们只需要几个组件即可在 React 中创建 PDF。现在,让我们回到主要设计。我们将使用相同的组件并添加一些样式,如 flex、边框样式、字体样式等。

解释每个 pdf 部分

我们先来创建标题。我们需要使用一个View组件作为标题,使用 应用一些样式flex,并向其添加Image和组件。Text

// src/MyDocument.js
import React from 'react';
import { Page, Text, View, Document, StyleSheet, Image } from '@react-pdf/renderer';

// Create styles
const styles = StyleSheet.create({
  page: {
    padding: 20,
    backgroundColor: '#ffffff'
  },
  section: {
    marginBottom: 20
  },
  headerContainer: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    marginBottom: 20
  },
  headerText: {
    fontSize: 20,
    fontWeight: 'bold'
  },
  image: {
    width: 50,
    height: 50
  },
  date: {
    fontSize: 12,
    textAlign: 'right'
  },
});
// Create Document Component
const MyDocument = () => {
  return (
        <Document>
      <Page size="A4" style={styles.page}>
        <View style={styles.section}>
          <View style={styles.headerContainer}>
            <Image style={styles.image} src="https://static.vecteezy.com/system/resources/thumbnails/013/993/061/small/mugiwara-the-illustration-vector.jpg" />
            <Text style={styles.headerText}>Anime Report</Text>
            <Text style={styles.date}>{new Date().toLocaleDateString()}</Text>
            </View>
          </View>
      </Page>
    </Document>
  );
};

export default MyDocument;
 

开始构建 pdf 报告

你看,这很容易掌握。

让我们编写表格。要使用 React PDF Renderer 创建表格,我们只需使用flex样式和View组件Text。每个View组件将包含一个组件,但您可以根据需要Text添加更多组件。Text

主要结构

此代码将在 PDF 文档中创建一个表格。

<View style={styles.table}>
  {/* Table Header */}
  <View style={styles.tableRow}>
    {/* Each Column Header */}
    <View style={styles.tableColHeader}>
      <Text style={styles.tableCellHeader}>Title</Text>
    </View>
    {/* More column headers... */}
  </View>
  {/* Table Rows */}
  {data.map((item, index) => (
    <View style={styles.tableRow} key={index}>
      {/* Each Column in a Row */}
      <View style={styles.tableCol}>
        <Text style={styles.tableCell}>{item.title}</Text>
      </View>
      {/* More columns... */}
    </View>
  ))}
</View>
 
  1. 表格容器

    <View style={styles.table}>
    

    View充当整个表格的主要容器。styles.table样式将定义表格的显示方式,如边框、填充等。

  2. 表头行

    <View style={styles.tableRow}>
    

    View表示表中的一行。该styles.tableRow样式将应用于标题行和每个数据行。

  3. 列标题

    <View style={styles.tableColHeader}>
    <Text style={styles.tableCellHeader}>Title</Text>
    </View>
    

    View标题行内的每个行都是一个列标题。styles.tableColHeader样式将定义标题单元格的外观,例如其背景颜色、边框和文本对齐方式。Text其内部的组件包含列的标题,并使用样式styles.tableCellHeader进行文本样式设置。对每个列标题重复此操作(例如,标题、工作室、类型、发布日期、状态、评级、成本)。

  4. 数据行

    {data.map((item, index) => (
    <View style={styles.tableRow} key={index}>
     {/* Columns for each row */}
    </View>
    ))}
    

    这里,我们使用map函数来循环遍历名为 的数组data。对于数组中的每个项目,它会在表中创建一个新行。该key属性可帮助 React 有效地管理项目列表。

  5. 数据行中的列

    <View style={styles.tableCol}>
    <Text style={styles.tableCell}>{item.title}</Text>
    </View>
    

    View数据行中的每个单元格都是一列。styles.tableCol样式将定义数据行中单元格的外观,而内部的Text组件将显示实际数据。styles.tableCell样式应用于文本以实现一致的样式。对数据行中的每一列重复此操作(例如item.title,、、、、、、)。item.studioitem.genreitem.releaseDateitem.statusitem.ratingitem.cost

  6. 表格代码

    // React PDF Renderer Component
    import React from 'react';
    import { Page, Text, View, Document, StyleSheet } from '@react-pdf/renderer';
    // Create styles
    const styles = StyleSheet.create({
    // after date styling....
    table: {
      display: "table",
      width: "auto",
      borderStyle: "solid",
      borderWidth: 1,
      borderColor: '#bfbfbf'
    },
    tableRow: {
      flexDirection: "row"
    },
    tableColHeader: {
      width: "15%",
      borderStyle: "solid",
      borderWidth: 1,
      borderColor: '#bfbfbf',
      backgroundColor: '#f0f0f0'
    },
    tableCol: {
      width: "15%",
      borderStyle: "solid",
      borderWidth: 1,
      borderColor: '#bfbfbf'
    },
    tableCellHeader: {
      margin: 5,
      fontSize: 10,
      fontWeight: "bold"
    },
    tableCell: {
      margin: 5,
      fontSize: 10
    },
    footerContainer: {
      flexDirection: 'row',
      justifyContent: 'space-between',
      alignItems: 'center',
      marginTop: 20
    },
    footerText: {
      fontSize: 12
    },
    totalCost: {
      fontSize: 12,
      fontWeight: 'bold'
    }
    });
    const data = [
    {
      title: 'Attack on Titan',
      studio: 'Wit Studio',
      genre: 'Action, Dark Fantasy',
      releaseDate: '04-07-2013',
      status: 'Completed',
      rating: '9.0',
      cost: '$120'
    },
    // You can add more or fetch data from an API or database
    ];
    // Create Document Component
    const MyDocument = () => (
    <Document>
    <Page size="A4">
       /* After header code */
      <View style={styles.table}>
        <View style={styles.tableRow}>
          <View style={styles.tableColHeader}>
            <Text style={styles.tableCellHeader}>Title</Text>
          </View>
          <View style={styles.tableColHeader}>
            <Text style={styles.tableCellHeader}>Studio</Text>
          </View>
          <View style={styles.tableColHeader}>
            <Text style={styles.tableCellHeader}>Genre</Text>
          </View>
          <View style={styles.tableColHeader}>
            <Text style={styles.tableCellHeader}>Release Date</Text>
          </View>
          <View style={styles.tableColHeader}>
            <Text style={styles.tableCellHeader}>Status</Text>
          </View>
          <View style={styles.tableColHeader}>
            <Text style={styles.tableCellHeader}>Rating</Text>
          </View>
          <View style={styles.tableColHeader}>
            <Text style={styles.tableCellHeader}>Cost</Text>
          </View>
        </View>
        {data.map((item, index) => (
          <View style={styles.tableRow} key={index}>
            <View style={styles.tableCol}>
              <Text style={styles.tableCell}>{item.title}</Text>
            </View>
            <View style={styles.tableCol}>
              <Text style={styles.tableCell}>{item.studio}</Text>
            </View>
            <View style={styles.tableCol}>
              <Text style={styles.tableCell}>{item.genre}</Text>
            </View>
            <View style={styles.tableCol}>
              <Text style={styles.tableCell}>{item.releaseDate}</Text>
            </View>
            <View style={styles.tableCol}>
              <Text style={styles.tableCell}>{item.status}</Text>
            </View>
            <View style={styles.tableCol}>
              <Text style={styles.tableCell}>{item.rating}</Text>
            </View>
            <View style={styles.tableCol}>
              <Text style={styles.tableCell}>{item.cost}</Text>
            </View>
          </View>
        ))}
      </View>
    </Page>
    </Document>
    );
    export default MyDocument;
    

    这里,我们创建了一个带有标题和数据行的简单表格。data数组中的每个项目都将成为表格中的一行,而项目的每个属性都将成为该行中的一个单元格。样式确保表格在 PDF 文档中看起来整洁而专业。

PDF 表格

现在,最后我们可以编写页脚。下面的代码创建一个页脚,其中包含一个图像和一个显示总成本的文本。

// style code after table styles...

  footerContainer: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    marginTop: 20
  },
  footerText: {
    fontSize: 12
  },
  totalCost: {
    fontSize: 12,
    fontWeight: 'bold'
  }

//... After table code add footer

<View style={styles.footerContainer}>
  <Image style={styles.image} src="https://static.vecteezy.com/system/resources/thumbnails/013/993/061/small/mugiwara-the-illustration-vector.jpg" />
  <Text style={styles.totalCost}>Total Cost: ${calculateTotalCost()}</Text>
</View>
 

View充当页脚的主要容器。styles.footerContainer样式定义页脚的显示方式,包括其布局、填充、边距和对齐方式。Image组件显示图像,而Text组件显示总费用。

结论

在本博客中,我们介绍了如何使用 React PDF Renderer 将 React 组件转换为高质量的 PDF。我们介绍了关键组件,包括文档、页面、视图、文本、图像和链接,并解释了它们的用途和样式。我们介绍了如何创建基本的 PDF 文档、添加页面、样式以及构建复杂的结构(如表格和页脚)。按照此步骤,您可以使用 React 轻松地将您的 Web 内容转换为可共享的 PDF。