文章目录
一、项目简介
本项目使用 Vue 3 搭配 PDF.js 构建一个支持目录、页面缩放和页码跳转的 PDF 在线阅读器组件,适用于后台管理系统、在线文档平台、电子书阅读等场景。
核心功能包括:
- 支持加载远程 PDF 文件
- 页面跳转与缩放控制
- 渲染页码与总页数
- 目录大纲展示
- 自适应页面宽度
二、项目结构
使用以下目录结构组织组件与逻辑:
三、PDF.js 引入与使用
3.1 安装依赖
npm install pdfjs-dist
3.2 初始化 PDF.js Worker
// src/utils/pdfWorker.js
import * as pdfjsLib from 'pdfjs-dist';
import pdfWorker from 'pdfjs-dist/build/pdf.worker.entry';
pdfjsLib.GlobalWorkerOptions.workerSrc = pdfWorker;
export default pdfjsLib;
四、核心组件开发:PdfViewer.vue
4.1 组件模板结构
<template>
<div class="pdf-container">
<div class="pdf-controls">
<button @click="prevPage">上一页</button>
<span>{{ currentPage }} / {{ totalPages }}</span>
<button @click="nextPage">下一页</button>
<select v-model="scale">
<option v-for="s in [0.5, 1, 1.5, 2]" :key="s" :value="s">缩放 {{ s }}x</option>
</select>
</div>
<canvas ref="canvasRef"></canvas>
</div>
</template>
4.2 组件逻辑功能
// src/components/PdfViewer.vue
<script setup>
import { ref, onMounted, watch } from 'vue';
import pdfjsLib from '@/utils/pdfWorker';
const props = defineProps({
pdfUrl: String
});
const pdfDoc = ref(null);
const currentPage = ref(1);
const totalPages = ref(0);
const scale = ref(1);
const canvasRef = ref(null);
const renderPage = async (pageNum) => {
const page = await pdfDoc.value.getPage(pageNum);
const viewport = page.getViewport({ scale: scale.value });
const canvas = canvasRef.value;
const context = canvas.getContext('2d');
canvas.height = viewport.height;
canvas.width = viewport.width;
const renderContext = {
canvasContext: context,
viewport: viewport
};
await page.render(renderContext).promise;
};
const loadPdf = async () => {
const loadingTask = pdfjsLib.getDocument(props.pdfUrl);
pdfDoc.value = await loadingTask.promise;
totalPages.value = pdfDoc.value.numPages;
renderPage(currentPage.value);
};
const nextPage = () => {
if (currentPage.value < totalPages.value) {
currentPage.value++;
}
};
const prevPage = () => {
if (currentPage.value > 1) {
currentPage.value--;
}
};
watch([currentPage, scale], () => {
renderPage(currentPage.value);
});
onMounted(() => {
loadPdf();
});
</script>
4.3 样式样例
<style scoped>
.pdf-container {
display: flex;
flex-direction: column;
align-items: center;
}
.pdf-controls {
margin-bottom: 1rem;
}
canvas {
border: 1px solid #ddd;
}
</style>
五、目录大纲支持(可选拓展)
你可以通过 getOutline()
获取 PDF 的目录并展示:
const outline = await pdfDoc.value.getOutline();
outline.forEach(item => {
console.log('章节标题:', item.title);
});
你可以进一步将其渲染为嵌套列表,实现目录跳转功能。
六、组件使用方式
在页面中使用组件:
<template>
<PdfViewer pdfUrl="/test.pdf" />
</template>
<script setup>
import PdfViewer from '@/components/PdfViewer.vue';
</script>
七、常见问题与优化建议
7.1 跨域问题
远程 PDF 地址若跨域未配置,需服务端支持 CORS 或改为本地代理加载。
7.2 大文件性能优化
- 延迟加载页码(分页懒加载)
- 限制初始渲染页
- 使用虚拟滚动加载多页内容
八、总结
通过整合 Vue 3 与 PDF.js,我们实现了一个功能完备、用户体验良好的在线 PDF 阅读器。它具备高度的可扩展性,你可以根据业务继续扩展目录跳转、批注、签名、下载等功能,打造属于你的文档系统。
到这里,这篇文章就和大家说再见啦!我的主页里还藏着很多 篇 前端 实战干货,感兴趣的话可以点击头像看看,说不定能找到你需要的解决方案~
创作这篇内容花了很多的功夫。如果它帮你解决了问题,或者带来了启发,欢迎:
点个赞❤️ 让更多人看到优质内容
关注「前端极客探险家」🚀 每周解锁新技巧
收藏文章⭐️ 方便随时查阅
📢 特别提醒:
转载请注明原文链接,商业合作请私信联系
感谢你的阅读!我们下篇文章再见~ 💕