在 React 中从 HTML 生成 PDF:导出数据网格的示例

2,100 阅读12分钟

原文链接:www.telerik.com/blogs/gener…

在 React 系列中生成 PDF 文件的第三篇博文中,我们将了解如何在高级 UI 组件(如数据网格和树列表)中导出内容和数据。

欢迎来到在 React 中生成 PDF 博文系列!

  • 在第 1 部分,在 React 中生成 PDF:像 1-2-3 一样简单,我们介绍了在 React 中生成 PDF 的基础知识,包括一些基本的 HTML 元素,并了解了在 React 中从 HTML 生成 PDF 文件的最快方法。
  • 在第 2 部分,在 React Demo 中从 HTML 生成 PDF:导出发票,我们关注一个常见场景:导出使用 HTML 和 CSS 创建的发票,并使用 React 将其内容导出为 PDF。这篇文章还介绍了我们如何包含具有独特符号的自定义字体,以及我们如何仅使用 CSS 控制生成的 PDF 文件的纸张大小。

现在我们将更深入地研究使用 React 将 HTML 和 CSS 导出为 PDF 的方法。具体来说,我们将看到一个将高级 React UI 组件(例如KendoReact Data GridReact TreeList)及其所有内容导出到 PDF 文件的示例。两个React 组件都内置了 PDF 导出功能,使导出就像单击按钮一样简单。

对于数据网格,我们还将完成使用本地数据添加分页的步骤。这是为了查看用于生成 PDF 文件的可用配置选项如何确定我们是仅导出当前视图还是导出数据表可用的所有数据。此外,我们可以配置是否只导出当前显示的数据、绑定到组件的所有数据(包括服务器上的数据),甚至在生成 PDF 文件时更改它的外观。

设置我们的 React 数据网格

安装 KendoReact 网格

在我们开始之前,我强烈建议您查看KendoReact Grid 入门页面,其中包含安装说明和一些有用的附加文档文章的链接,这些文章有助于理解 React Data Grid。

下面的一切都假设我们已经建立了一个现有的 React 项目。具体来说,一个使用create react app.

第一步是安装正确的 npm 包,我们可以通过复制和粘贴我们刚刚链接到的文章中的 npm install 命令来完成。

npm install --save @progress/kendo-react-grid @progress/kendo-data-query @progress/kendo-react-data-tools @progress/kendo-react-inputs @progress/kendo-react-intl @progress/ kendo-react-dropdowns @progress/kendo-react-dateinputs @progress/kendo-drawing @progress/kendo-react-animation @progress/kendo-licensing

我们还需要安装我们想要在我们的应用程序中使用的主题。KendoReact 支持三种设计语言——Kendo UI 默认主题、Bootstrap 或 Material Design。在下面的所有示例中,我们将使用 Material 主题,但样式和主题概览页面包含有关如何安装您喜欢的主题的说明。

如前所述,我们将使用 Material 主题,所以让我们也安装它。

npm install --save @progress/kendo-theme-material

注意:如果您之前没有使用过 KendoReact,您还应该按照本文中突出显示许可证密钥激活步骤进行操作

完成安装步骤后,我们可以在 React 应用程序中添加适当的导入语句。在我们的 App.js 中,我们可以添加以下内容:

正如我们所看到的,我们现在已经导入了 Material Design 主题以及我们需要的适当的特定于网格的项目。

添加数据和定义网格

KendoReact 数据表 ( React Data Grid ) 可以轻松绑定到几乎任何类型的对象,为了使事情变得简单,我们将只使用简单的对象数组。一旦我们知道对象上可用的字段,我们就可以在 Grid 声明中定义<Column />组件,并使用 field 属性将列链接到适当的字段。

为了让每个人都能轻松参考,这里有一个 StackBlitz 项目,我们在其中添加了示例数据以通过 -grid-sample-products.jsx导入为- 然后定义一个带有列子gridSampleProducts集的 React Grid。

添加分页

分页作为一个概念,允许用户以较小的块大小接收数据密集型组件,例如 React 数据表,而不是带有巨大滚动条的巨大数据项列表。分页还有其他几个好处,包括性能,因为需要一次显示更少的数据。

今天分页将有助于展示我们如何在网格中自定义生成 PDF 的内容。具体来说,我们是想只导出当前页面的数据项,还是想导出可以在数据网格的所有页面上找到的所有数据?在我们的例子中,所有数据都将立即提供给网格,这甚至可以轮询服务器以获取所有可用数据并生成 PDF 文件。因此,这是一个非常强大的功能,可以开箱即用。

为了最好地理解分页,KendoReact 数据网格分页文档文章提供了有关如何实现分页的深入信息和示例。

构建我们上面链接的 StackBlitz 示例,我们需要导入一个我们最初安装的额外 npm 包,并从 React 导入一些额外的部分,以确保我们可以开始使用钩子。因此,在我们的 App.js 中,我们可以添加:

对于那些感兴趣的人,该@progress/kendo-data-query是一个帮助程序库,KendoReact 提供它以一种格式转换数据,KendoReact 数据网格可以轻松地使用它来帮助解决分页、排序、过滤、分组等方面的问题。把它作为一个单独的包提供了一些关注点的分离,并帮助 React 数据表具有超高性能,因为很多处理都发生在数据查询库中。

现在,要理解分页,需要考虑几个概念。首先,只需几个变量就可以完成对大型数据集合的分页:

  • 数据数组
  • 在一页上显示的项目总数——这被称为页面大小,或take(“从我们的数据中提取这么多数据项”)
  • 我们当前在数据数组中的位置——这有助于我们跟踪我们在哪个页面;也被调用skip是因为我们可以计算我们需要跳过多少数据项(如果我们知道当前页面和页面大小)

一旦我们记住了这些,我们还需要根据这些信息为网格定义一个状态。将这些概念带入代码和我们的 App.js 中:

有了这个配置,我们现在说我们要取五个数据项,我们跳过零项,这意味着我们从 0 开始计数到 5。

现在来自数据查询库的一些初始魔法。如果我们想要获取一个数组并将其转换为我们的数据网格可以用于分页的内容,我们只需调用 process() 函数:

就这么简单!

现在,有了手头的数据,我们可以更新我们的 Grid 以从我们的 processingData 变量中获取数据并设置 pageable 属性让 Grid 知道我们想要在 Grid 底部显示分页器。

我们不需要完全写出 pageable={true} 作为这个 prop 定义为 true 时的默认值。此外,我们可以绑定我们的 skip 和 take 变量,这些变量用于在寻呼机底部显示“X - Y of Z”数据项。数学都是自动处理的。我们的变量中有这些变量,dataState因此我们可以使用 JS 扩展运算符将这些属性应用于我们的 Grid 配置,而不是手动输入(有点节省时间)!

最后要介绍的项目是onDataStateChange事件,它会在 React 数据网格中的任何数据更改时触发。对我们来说,这意味着分页,但这也会触发排序、分组、过滤等。以下是我们可以用于此事件的内容:

在这种情况下,我们定义了一个回调,它将获取包含 take 和 skip 变量的事件参数,以指示我们在数据中的位置。然后我们更新组件的当前状态以确保 Grid 知道新的跳过和取值。这将适用于向前和向后翻页!

这是一个 StackBlitz 项目,显示了到目前为止的所有内容。

完成所有这些后,我们现在可以添加一些 PDF 生成了!

从 KendoReact 数据网格生成 PDF 文件

如果您已阅读本博客文章系列的第 1 部分和第 2 部分,您就会知道我们必须安装和导入KendoReact PDF Processing 库

import * as React from 'react';
导入'@progress/kendo-theme-material/dist/all.css';
导入'./style.css';
从“@progress/kendo-react-grid”导入 { Grid, GridColumn as Column };

当我们再次安装东西时,让我们添加KendoReact ButtonReact Checkbox组件,因为我们将使用它们进行一些动态配置。

我们还将更新我们的 import 语句以不仅包含这些新包,而且还会从 React添加useRef

与其他博客文章中一样,导出为 PDF 的本质是用标签包裹我们的 Grid 组件。如果我们只是用这个标签环绕我们当前的 Grid 元素,那么 Grid 就会消失我们的页面,因为整个元素只负责导出为 PDF。因此,我们基本上需要加倍以显示 Grid 元素。为了使这更容易,我们可以定义一个可以重用的新元素。

然后我们可以更新我们的标记为:

我们在这里有一个新的引用,pdfExportRef,我们可以将它添加到我们的 App.js 文件的开头,在那里我们设置我们所有的钩子等等。

我们应该添加的另一个变量是让我们知道我们是否正在主动导出内容,因为我们需要禁用导出按钮。这将确保用户不会多次单击我们的导出按钮来生成 PDF 文件。当我们导出可能需要一些时间来生成的大型数据集时,这变得尤为重要。我们还将提示用户选择下载文件的位置。

如果我们更深入地查看我们的新 Grid 标记,我们会看到我们的 Grid Toolbar 中有一个需要事件处理程序的按钮元素。

我们在这里所做的是获取我们的 Grid 引用,更新我们正在导出的内容,然后调用 .save() 函数以开始导出过程。我们还传递onPdfExportDone给我们一个回调函数,以便在生成文件后挂钩并执行某些操作。在这种情况下,我们只需要设置isPdfExporting为 false。

如果我们在当前状态下运行这段代码,我们就可以开始生成 React PDF 文件了!但是,您会注意到我们只导出当前页面。在我们的意义上,我们每次只获得五个数据项,因此实际上并未导出第二页。让我们更新内容以涵盖这种情况,以便我们可以一次导出所有数据。

导出所有数据

为了更容易看出一个导出和另一个导出之间的区别,让我们设置一个复选框来确定我们是导出所有页面还是仅导出一个页面。

现在我们只需要定义我们定义allPageCheck其余钩子的位置。

allPageChange事件是相当简单的,我们只是在倒车任何变量当前设置为。

最后一步是更新 onPdfExport 以检查我们是导出所有行还是仅导出当前页面。

请注意,在这种情况下,我们调用.save()并传入所有数据而不是processedData变量。如果我们在服务器上有其他数据,这将是我们向后端发出请求并在客户端上没有可用数据时获取所有数据的地方。

我们需要添加的另一段代码以确保我们涵盖了 processingData 实际上没有数据的边缘情况如下:

当没有可用数据时,这会将我们所在的页面“重置”到第一页,这可能是我们在导出期间动态更新网格数据时的情况。本质上,当我们导出所有页面时,这将成为让我们遍历数据并导出每一行的一段代码。

一次处理可能有很多,所以为了让事情变得更容易,这里有一个 StackBlitz 项目,它显示了所有东西的启动和运行。

有了这一切,我们现在有了一个数据网格,可以从当前数据集或整个数据集一次性生成 PDF 文件。

使用 React TreeList 生成 PDF 文件

KendoReact的TreeList是非常相似的阵营数据网格,所以我想以包括的TreeList作为参考的类似样品。由于我们花费了一些时间来启动和运行 Grid 项目,并且 TreeList 配置与 Grid 的配置基本相同,因此我不再重复每一步,而是将接力棒传递给您:这是一个 StackBlitz 项目,展示了如何这可以为 TreeList 完成。

PDF 所有的东西!

这篇博文确实涵盖了很多内容,所以让我们总结一下我们所做的。

  • 我们使用示例数据集配置了 KendoReact 数据网格。
  • 我们配置了数据网格以允许分页,处理如何使用跳过和获取向前和向后翻页。
  • 我们使用 KendoReact PDF Processing Library 将数据表的当前页面导出为 PDF 文件。
  • 我们添加了一个复选框来选择是否从数据表渲染 PDF 应仅包含当前页面或所有可用数据。
  • 最后,我们还看到了如何从 React Tree Grid 组件生成 PDF 文件的示例!

之间的阵营生成PDF:1-2-3一样容易从HTML生成PDF的阵营演示:出口发票,而这篇博客文章,你现在有上多么强大办理好KendoReact PDF生成库即可。除了简单的 HTML,我们还可以从我们的 React 应用程序中生成 PDF 文件,其中包含更复杂的场景,例如发票,甚至是高级数据组件,例如 KendoReact 数据网格和 TreeList 组件!

如果您喜欢到目前为止所见,下一步就是了解KendoReact——我们专业的 React UI 组件和数据可视化库。KendoReact 为 React 从头开始构建,适用于任何现有的 UI 堆栈。其 90 多个可自定义且功能丰富的组件(包括您刚刚阅读的 PDF 导出功能)使其成为您内部 UI 库的完美基础。