
前言
在前端开发里,有时候会遇到需要在网页中展示 PDF 文档预览功能,比如合同 ERP、销售 CRM、内部文档 CMS 管理系统,内置 PDF 文件在线预览功能。Vue 3 作为流行的 JavaScript 框架,为开发者提供了强大的工具和生态系统。而 pdf.js 是 Mozilla 开发的一个基于 HTML5 的开源 PDF 渲染库,它能让我们在浏览器中无需借助第三方插件就可以直接展示 PDF 文件。本文会详细阐述如何在 Vue 项目里使用vue-pdf-embed 来展示 PDF 文档,让网页具备出色的文档展示能力。
一、概述
1.1 关于 PDF.js
PDF.js 是由 Mozilla 开发的一款开源 JavaScript 库,旨在通过纯前端技术实现 PDF 文件的在线预览,无需依赖任何浏览器插件。其核心架构基于 HTML5 与 Canvas 技术,结合 JavaScript 解析 PDF 文件内容,实现跨浏览器兼容性。该库采用分层设计,主要包括 PDF 解析层、页面渲染层和用户交互层。PDF.js 通过 Web Worker 处理 PDF 解析任务,避免阻塞主线程,从而提升性能。其渲染机制采用 Canvas 绘制页面内容,并通过视口适配技术实现页面缩放与滚动,确保在不同设备和分辨率下的良好显示效果。
一般来说,要查看 PDF 文档,我们需要一个 PDF 阅读器软件,而通过 PDF.js 可以在浏览器中直接显示和处理 PDF 文档,无论是在线浏览、存档或者其他基于 PDF 的功能都可以实现。
pdf.js官网:mozilla.github.io/pdf.js/
1.2 关于 vue-pdf-embed
作为基于 Vue 生态的组件,vue-pdf-embed 是一个专为 Vue 设计的PDF 查看器组件,底层基于 Mozilla 强大的 PDF.js 引擎构建,但去除了所有不必要的 UI 和复杂性,为开发者提供了在 Web 应用中无缝展示PDF文档的完整能力。这个组件通过创新的技术架构和优化的渲染机制,彻底改变了传统PDF嵌入的局限性。而且 vue-pdf-embed 提供了更丰富的功能,支持密码保护文档、文本选择和搜索、完整的注释层显示、灵活的页面控制(缩放、旋转)以及出色的跨设备响应式性能。
| 功能特性 | 传统iframe方案 | vue-pdf-embed方案 |
|---|---|---|
| 文本选择功能 | ❌ 无法实现 | ✅ 完美支持 |
| 文档搜索能力 | ❌ 功能缺失 | ✅ 内置实现 |
| 注释层显示 | ❌ 不支持 | ✅ 可选开启 |
| 页面精确控制 | ❌ 限制较多 | ✅ 灵活配置 |
| 性能表现 | ❌ 加载缓慢 | ✅ 优化出色 |
1.2 核心亮点
在众多 PDF 显示方案中,vue-pdf-embed 脱颖而出,原因在于它的零配置开箱即用特性。无需复杂的设置过程,只需简单安装即可开始使用。更重要的是,它支持多种PDF数据源,包括URL链接、Base64编码、二进制数据等,满足各种实际应用场景的需求。
| 核心价值 | 技术优势 |
|---|---|
| 零配置开箱即用 | 基于PDF.js,无需复杂的对等依赖或额外配置,简化安装和使用过程 |
| 性能极致优化 | Web Worker支持,内存占用合理 |
| 开发体验提升 | TypeScript原生支持,完整类型定义 |
| 精确渲染控制 | 在Vue应用中实现对PDF文档渲染的精准掌控,开发者可根据需求灵活展示文档内容 |
| 密码保护支持 | 能够处理密码保护的PDF文档,确保用户在有权限的情况下查看文档内容 |
| 文本层与注释层 | 包含文本层,使文档可搜索和选择,提升用户交互体验。同时具备注释层,支持注释和链接显示 |
| 浏览器直接使用 | 可直接在浏览器中使用,方便快捷地集成到项目中 |
二、快速上手 🚀
2.1 安装依赖
万事开头难,但 vue-pdf-embed 的起步却异常简单。首先,确保有一个正在开发的Vue 3项目。我用的是Vite + Vue 3 + TypeScript的组合,这也是目前最主流和高效的开发栈。

进入项目根目录,执行安装命令:
bash
# npm
npm install vue-pdf-embed
# yarn
yarn add vue-pdf-embed
# pnpm(推荐)
pnpm add vue-pdf-embed
注意:pdfjs-dist 是核心依赖,必须同时安装,版本建议选择3.x+以兼容 Vue3。
2.2 引入插件
在安装完成后,我们需要在项目中引入并配置 vue-pdf-embed,在需要使用该功能的 Vue 文件中直接引入:
javascript
import VuePdfEmbed from 'vue-pdf-embed'
// 可选样式文件,增强显示效果(如果需要支持文本选择和注释交互)
import 'vue-pdf-embed/dist/styles/annotationLayer.css'
import 'vue-pdf-embed/dist/styles/textLayer.css'
vue-pdf-embed 依赖 pdfjs-dist 进行底层解析,如果未正确配置 Web Worker 的路径,会导致解析引擎初始化失败。在引入组件的同时,手动引入 pdfjs-dist 并配置 workerSrc,建议在组件渲染前完成此设置:
javascript
import VuePdfEmbed from 'vue-pdf-embed'
import * as PDFJS from 'pdfjs-dist'
// 配置 worker 路径(Vite 环境下推荐使用 new URL 的方式)
PDFJS.GlobalWorkerOptions.workerSrc = new URL(
'pdfjs-dist/build/pdf.worker.min.mjs',
import.meta.url
).toString()
2.3 基础用法示例
全局注册后,在任意组件中直接使用,仅需几行核心代码,即可实现 PDF 预览。理论说再多,不如直接看代码。
html
<script setup lang="ts">
import VuePdfEmbed from 'vue-pdf-embed'
const pdfUrl = ref('https://cdn.jsdelivr.net/gh/mozilla/pdf.js/web/compressed.tracemonkey-pldi-09.pdf');
</script>
<template>
<VuePdfEmbed :source="pdfUrl" />
</template>
就是这么简单!几行代码就能在页面中嵌入一个完整的PDF查看器。
三、核心功能深度解析
3.1 灵活的页面控制
在文档管理系统中,PDF 预览是核心功能之一。vue-pdf-embed 通过 page 属性可以指定显示特定页码或页码范围,满足不同场景需求:
javascript
// 显示特定页面
<VuePdfEmbed :page="3" :source="pdfSource" />
// 显示多个页面
<VuePdfEmbed :page="[1, 5, 8]" :source="pdfSource" />
3.2 加载状态与错误处理
html
<script setup lang="ts">
import VuePdfEmbed from 'vue-pdf-embed'
import { PDFDocumentProxy} from "pdfjs-dist/types/src/display/api";
const pdfUrl = ref('https://cdn.jsdelivr.net/gh/mozilla/pdf.js/web/compressed.tracemonkey-pldi-09.pdf');
// PDF加载完成时回调
const handleDocumentLoaded = (pdfDocument: PDFDocumentProxy) => {
console.log('PDF文档加载成功,总页数:', pdfDocument.numPages);
// 这里可以做一些初始化操作,比如更新总页数到状态管理
};
// 加载失败回调
const handleLoadError = (error: Error) => {
console.error('PDF文档加载失败:', error);
// 这里可以给用户一个友好的错误提示,比如"文档加载失败,请重试或检查文件"
};
</script>
<template>
<VuePdfEmbed :source="pdfUrl" @loaded="handleDocumentLoaded" @error="handleLoadError" :width="1400" />
</template>
PDFDocumentProxy 是 PDF.js 库提供的一个核心对象,它代表了一个已经加载的 PDF 文档,通常会在 PDF 文件加载完成后的回调事件中获取到它。
| 核心属性与用法 | 简要说明 |
|---|---|
| numPages | 这是最常用的属性,用于获取当前 PDF 文档的总页数 |
| fingerprint | PDF 文档的唯一指纹标识 |
| getPage(pageNumber) | 传入页码,返回一个 Promise。 解析后得到指定页的 PDFPageProxy 对象,用于进一步渲染或获取页面尺寸等信息 |
| destroy() | 销毁该文档对象,释放相关内存 |
3.3 加载进度跟踪
html
<script setup lang="ts">
import VuePdfEmbed from 'vue-pdf-embed'
import { OnProgressParameters } from "pdfjs-dist/types/src/display/api";
const pdfUrl = ref('https://cdn.jsdelivr.net/gh/mozilla/pdf.js/web/compressed.tracemonkey-pldi-09.pdf');
const handleProgress = (progress: OnProgressParameters) => {
console.log('加载进度:', progress)
};
const handleRenderingFinished = () => {
console.log('PDF文档渲染完成');
};
// 文档渲染失败回调
const handleRenderingFailed = (error: Error) => {
console.error('PDF文档渲染失败:', error);
};
</script>
<template>
<VuePdfEmbed
ref="vuePdfRef"
:source="pdfUrl"
@progress="handleProgress"
@renderingFailed="handleRenderingFailed"
@rendered="handleRenderingFinished" />
</template>
3.4 加密文档处理
当PDF文件需要密码保护时,vue-pdf-embed 也能优雅地处理:
html
<script setup>
import VuePdfEmbed from 'vue-pdf-embed'
const handlePasswordRequest = (event) => {
const password = prompt('请输入PDF密码:')
if (password) {
event.callback(password)
}
}
</script>
<template>
<VuePdfEmbed
:source="pdfSource"
@password-requested="handlePasswordRequest"
/>
</template>
四、API 参考手册
4.1 属性
通过简单的属性(Props)来精确控制 PDF 的展示效果
| 属性 | 类型 | 候选值 | 简要说明 |
|---|---|---|---|
| source | 文档源,支持 URL 链接、Base64 编码、二进制数据等 | ||
| width | number | 自定义渲染的宽度 | |
| height | number | 自定义渲染的高度 | |
| page | number number[] | 指定显示的页码,不指定则显示所有页 | |
| scale | number | 页面的缩放比例 | |
| rotation | number | 0、90、180、270 | 旋转角度,比如0就是不旋转,+90,-90 就是水平旋转 |
| textLayer | boolean | 是否启用文本层,允许用户在网页中复制、搜索 PDF 里的文字 | |
| annotationLayer | boolean | 是否启用注释层,显示 PDF 中的超链接、备注等交互元素 | |
| linkService | 文档导航服务 | ||
| imageResourcesPath | string | 注释层中使用的图标路径 |
4.2 事件处理机制
vue-pdf-embed 提供完整的事件系统,能够监控 PDF 加载和渲染的各个环节:
| 事件名 | 简要说明 |
|---|---|
| internal-link-clicked | 内部链接被点击时触发 |
| loaded | PDF 文档加载完成时触发 |
| loading-failed | PDF 加载失败时触发 |
| password-requested | 需要密码才能打开 PDF 时触发 |
| progress | 跟踪文档加载进度 |
| rendered | 文档渲染完成时触发 |
| rendering-failed | 文档渲染失败时触发 |
4.3 方法
| 方法名 | 参数 | 简要说明 |
|---|---|---|
| print(resolution, fileName, allPages) | resolution:打印分辨率,默认300 fileName:文件名 allPages:是否打印所有页,默认值 false | 通过浏览器打印文档 |
| download(fileName) | 下载文档 |
4.4 插槽
| 插槽名 | 简要说明 |
|---|---|
| after-page | 每页后需添加的内容 |
| before-page | 每页前需添加的内容 |
总结
vue-pdf-embed 是 Vue 3 生态中轻量、易用的 PDF 预览组件,基于 pdfjs-dist 封装,无需关注底层解析逻辑。作为 Vue 生态中 PDF 处理的标杆项目,通过持续的技术创新和生态建设,为开发者提供了简单、高效、可靠的 PDF 文档嵌入能力,是现代化 Web 应用中处理 PDF 文档的首选技术方案。
