当前位置: 首页 > news >正文

Vue 3 实战:从零到一用 vue-pdf-embed 打造功能齐全的 PDF 查看器

你好,Vue 开发者们!

在 Web 开发中,我们经常会遇到需要在页面中直接展示 PDF 文件的需求,例如预览合同、显示报告或在线阅读文档。你可能会想到用 <iframe> 或者一些重量级的库,但它们往往不够灵活或过于臃肿。

今天,我将向你介绍一个轻量、强大且对 Vue 3 非常友好的解决方案——vue-pdf-embed

🤔 vue-pdf-embed 是什么?

vue-pdf-embed 是一个专门为 Vue 设计的 PDF 查看器组件。它基于 Mozilla 的 PDF.js,但去除了所有不必要的 UI 和复杂性,只专注于提供一个纯粹、高性能的 PDF 渲染核心。

核心亮点:

  • 📦 轻量级:只包含渲染 PDF 所需的核心逻辑,打包体积小。
  • 🖼️ 高质量渲染:利用 PDF.js,确保 PDF 内容清晰、准确地显示。
  • 📱 响应式:能够很好地适应不同尺寸的容器。
  • 🔧 高度可控:通过 Props 和事件,你可以完全控制 PDF 的渲染行为,如页码、缩放、旋转等。
  • ✨ Vue 3 兼容:完美支持 Vue 3 的组合式 API 和 <script setup> 语法。

🛠️ 安装

将 vue-pdf-embed 添加到你的项目中非常简单:

npm install vue-pdf-embed

🚀 快速上手:三分钟渲染你的第一个 PDF

集成 vue-pdf-embed 只需要几行代码。

1. 引入组件

<script setup>
import VuePdfEmbed from "vue-pdf-embed";
</script>

2. 在模板中使用

你需要提供一个 source 属性,指向你的 PDF 文件。它可以是一个 URL、Base64 字符串或 ArrayBuffer。

<template><VuePdfEmbedsource="https://raw.githubusercontent.com/mozilla/pdf.js/master/web/compressed.tracemonkey-pldi-09.pdf"/>
</template>

就这样!一个 PDF 查看器已经成功渲染在你的页面上了。是不是超级简单?


✨ 进阶实战:打造一个功能齐全的 PDF 查看器

当然,仅仅显示 PDF 是不够的。我们通常需要分页、缩放等功能。下面,我们将创建一个更完整的 PDF 查看器组件。

核心思路

  1. 加载 PDF:监听 @loaded 事件,在 PDF 加载完成后获取总页数。
  2. 分页控制:创建“上一页”和“下一页”按钮,通过修改 page prop 来切换页面。
  3. 缩放控制:创建“放大”和“缩小”按钮,通过修改 scale prop 来调整视图大小。
  4. 状态显示:显示当前页码和总页数。

完整代码示例 (PdfViewer.vue)

<template><div class="pdf-viewer-container"><!-- 控制栏 --><div class="controls"><button @click="prevPage" :disabled="page <= 1">上一页</button><span>第 {{ page }} / {{ pageCount }} 页</span><button @click="nextPage" :disabled="page >= pageCount">下一页</button><button @click="zoomOut" :disabled="scale <= 0.5">缩小</button><span>缩放: {{ Math.round(scale * 100) }}%</span><button @click="zoomIn" :disabled="scale >= 2">放大</button></div><!-- PDF 渲染区域 --><div class="pdf-wrapper"><VuePdfEmbedref="pdfRef":source="pdfSource":page="page":scale="scale"@loaded="handleDocumentLoaded"@rendering-failed="handleRenderingFailed"/></div></div>
</template><script setup>
import { ref, watch } from "vue";
import VuePdfEmbed from "vue-pdf-embed";// PDF 文件源
const pdfSource = ref("https://raw.githubusercontent.com/mozilla/pdf.js/master/web/compressed.tracemonkey-pldi-09.pdf"
);// PDF 组件引用
const pdfRef = ref(null);// PDF 状态
const page = ref(1);
const pageCount = ref(0);
const scale = ref(1);// PDF 加载完成回调
function handleDocumentLoaded(pdf) {console.log("PDF 加载完成!", pdf);pageCount.value = pdf.numPages;
}// PDF 渲染失败回调
function handleRenderingFailed(error) {console.error("PDF 渲染失败:", error);
}// 分页功能
function prevPage() {if (page.value > 1) {page.value--;}
}function nextPage() {if (page.value < pageCount.value) {page.value++;}
}// 缩放功能
function zoomIn() {if (scale.value < 2) {scale.value += 0.25;}
}function zoomOut() {if (scale.value > 0.5) {scale.value -= 0.25;}
}// 监听页码变化,确保在范围内
watch(page, (newPage) => {if (newPage < 1) {page.value = 1;}if (newPage > pageCount.value && pageCount.value > 0) {page.value = pageCount.value;}
});
</script><style scoped>
.pdf-viewer-container {max-width: 900px;margin: 2rem auto;border: 1px solid #ccc;border-radius: 8px;box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}.controls {display: flex;justify-content: center;align-items: center;gap: 1rem;padding: 1rem;background-color: #f5f5f5;border-bottom: 1px solid #ccc;border-radius: 8px 8px 0 0;
}.controls button {padding: 0.5rem 1rem;border: 1px solid #ddd;border-radius: 4px;background-color: #fff;cursor: pointer;
}.controls button:disabled {cursor: not-allowed;opacity: 0.5;
}.controls span {font-size: 0.9rem;min-width: 100px;text-align: center;
}.pdf-wrapper {height: 70vh;overflow: auto;background-color: #e9e9e9;padding: 1rem;
}/* vue-pdf-embed 的内部样式,我们可以覆盖它 */
:deep(.vue-pdf-embed > div) {margin-bottom: 8px;box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
}
</style>

常用 Props 和事件

  • Props:
  • source: PDF 文件来源 (URL, Base64, Uint8Array, …)。
  • page: (Number) 要显示的页码。
  • scale: (Number) 缩放比例。
  • rotation: (Number) 旋转角度 (0, 90, 180, 270)。
  • width: (Number | String) 容器宽度。
  • height: (Number | String) 容器高度。
  • Events:
  • @loaded: PDF 文档加载完成时触发,回调参数为 PDF.js 的文档对象,可以从中获取总页数 numPages 等信息。
  • @rendered: 所有可见页面渲染完成时触发。
  • @rendering-failed: 渲染失败时触发。
  • @password-requested: 当 PDF 需要密码时触发。

总结

vue-pdf-embed 为在 Vue 应用中嵌入 PDF 提供了一个极其简单而又强大的解决方案。它避免了 <iframe> 的笨重和同源策略问题,也比一些重量级 UI 库更轻量、更灵活。

通过组合其 Props 和事件,你可以轻松构建出符合业务需求的、交互丰富的 PDF 查看器。如果你正在寻找一个可靠的 Vue PDF 渲染方案,vue-pdf-embed 绝对是你的不二之选。

 Vue 3 实战:从零到一用 vue-pdf-embed 打造功能齐全的 PDF 查看器 - 高质量源码分享平台-免费下载各类网站源码与模板及前沿技术分享


文章转载自:

http://qHmrpEO8.bqppr.cn
http://PLpethU6.bqppr.cn
http://O7zTNQyR.bqppr.cn
http://JO077P1J.bqppr.cn
http://guHGD0C9.bqppr.cn
http://2zYdS4W9.bqppr.cn
http://TCvE2m0T.bqppr.cn
http://i3MfSv4m.bqppr.cn
http://bs0QQCAP.bqppr.cn
http://0v9ihbPi.bqppr.cn
http://U8IQ1kdf.bqppr.cn
http://Ikgie8E9.bqppr.cn
http://FhHUoshP.bqppr.cn
http://zElB8bOV.bqppr.cn
http://UCH6V86Z.bqppr.cn
http://OcSSokfo.bqppr.cn
http://VDP24GT0.bqppr.cn
http://EXU9D08t.bqppr.cn
http://cToOOLgH.bqppr.cn
http://rCahox3f.bqppr.cn
http://r4P2kyJ3.bqppr.cn
http://Bk3fA7ao.bqppr.cn
http://Jevrikc3.bqppr.cn
http://YoZ2zwpt.bqppr.cn
http://hZaKuZJb.bqppr.cn
http://SjUKpwlX.bqppr.cn
http://b34h1pz8.bqppr.cn
http://3WJFG4Gu.bqppr.cn
http://vMBXEJOm.bqppr.cn
http://jrEv0IUh.bqppr.cn
http://www.dtcms.com/a/376293.html

相关文章:

  • Redis超详细入门教程
  • 单例模式(C++)详解(2)
  • 卷发棒/卷发梳MCU方案分析
  • vue3+TS项目配置unocss
  • 恒拓高科BeeWorks亮相鸿蒙 HEC 生态大会,重构数字化协作免费新体验
  • 抖音矩阵号管理+视频剪辑+智能体开发接入 SaaS源码
  • HarmonyOS 应用开发深度解析:驾驭 ArkTS 声明式 UI 与现代化状态管理
  • HarmonyOS之UIAbilityContext详解
  • HarmonyOS 应用开发深度解析:基于 Stage 模型的 ArkUI 声明式开发实践
  • 数学建模常用算法-模拟退火算法
  • 数据分析之Pandas入门小结
  • Maya绑定:变形器、高级复制、晶格
  • infinityfree 网页连接内网穿透 localtunnel会换 还是用frp成功了
  • 【三维重建】3R-GS:优化相机位姿的3DGS最佳实践
  • 稳态太阳光模拟器 | 多源分布式设计的要点有哪些?
  • 【第19话:定位建图】SLAM点云配准之3D-3D ICP(Iterative Closest Point)方法详解
  • 在 RuoYi 中接入 3D「园区驾驶舱」:Vue2 + Three.js + Nginx
  • tp5的tbmember表闭包查询 openid=‘abc‘ 并且(wx_unionid=null或者wx_unionid=‘‘)
  • PPT转化成PDF脚本
  • 基于 Dockerfile 构建镜像
  • Linux学习记录--消息队列
  • leetcode算法刷题的第三十一天
  • Linux驱动开发(2)进一步理解驱动
  • Linux驱动开发笔记(十)——中断
  • 推荐一款智能三防手机:IP68+天玑6300+PoC对讲+夜视
  • 栈:逆波兰表达式求解
  • nginx中ssl证书的获取与配置
  • 云平台得大模型使用以及调用
  • 手写简单的int类型顺序表
  • Spring Boot 深入剖析:BootstrapRegistry 与 BeanDefinitionRegistry 的对比