Vue预览PDF的两种方法比较(vue-pdf-embed与pdfjs-dist)

 更新时间:2025年08月17日 09:38:51   作者:VipSoft  
这篇文章主要为大家详细介绍了Vue预览PDF的两种方法比较,即vue-pdf-embed与pdfjs-dist,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下

简介

Vue PDF预览,vue-pdf-embedpdfjs-dist 的比较

  • 如果 PDF < 5MB → 用 vue-pdf-embed(简单快捷)。
  • 如果 PDF > 5MB → 用 pdfjs-dist + 分页懒加载(稳定可控)。

PDFJS.getDocument TypeError: Cannot read from private field

pnpm install pdfjs-dist@2.14.305 --save

package.json,pdfjs-diist版本使用@2.11.338,高版本会报错

"dependencies": {
    "pdfjs-dist": "^2.11.338",
    "vue": "^3.5.13",
    "vue-i18n": "^11.1.2",
    "vue-router": "^4.5.0"
  },
  "devDependencies": {
    "@types/node": "^22.13.10",
    "@types/pdfjs-dist": "^2.10.378",
    "@vitejs/plugin-vue": "^5.2.1",
    "typescript": "^5.8.2",
    "vite": "^6.2.1",
    "vue-tsc": "^2.2.8"
  }

vue-pdf-embed 与 pdfjs-dist 的比较与选择

主要区别

特性vue-pdf-embedpdfjs-dist
性质Vue专用封装组件PDF.js的纯JS库
集成难度简单,开箱即用需要自行实现渲染逻辑
功能完整性基础功能完善功能最全面
自定义程度有限,通过props配置完全自定义
维护性社区维护Mozilla官方维护
体积较小(封装后)较大(完整功能)
文档支持社区文档官方完善文档

应用场景

推荐使用vue-pdf-embed的情况:

  • 快速在Vue项目中集成PDF预览功能
  • 不需要高度自定义的PDF渲染
  • 项目时间紧迫,需要快速实现
  • 只需要基础查看功能(缩放、翻页等)
  • 项目对包体积较敏感

推荐使用pdfjs-dist的情况:

  • 需要深度自定义PDF渲染(如自定义工具栏、注释系统)
  • 需要高级功能(文本选择、搜索、表单填写等)
  • 项目已在使用PDF.js相关生态
  • 需要处理特殊的PDF渲染需求
  • 需要直接访问PDF.js底层API

具体推荐

对于大多数Vue项目 -推荐 vue-pdf-embed

优势

// 使用极其简单
<template>
  <vue-pdf-embed 
    :source="pdfUrl" 
    :page="currentPage"
    @rendered="onRendered"
  />
</template>
  • 几行代码即可实现完整功能
  • 内置分页、缩放等常见功能
  • 专为Vue设计,响应式集成好
  • 避免直接操作PDF.js的复杂性

需要高级功能时 -推荐 pdfjs-dist

典型复杂场景

// 自定义渲染示例
const renderPage = async (pageNum) => {
  const page = await pdf.getPage(pageNum);
  const viewport = page.getViewport({ scale: 1.5 });
  
  // 自定义canvas渲染
  const canvas = document.getElementById('canvas');
  const context = canvas.getContext('2d');
  canvas.height = viewport.height;
  canvas.width = viewport.width;
  
  // 添加自定义渲染逻辑
  const renderContext = {
    canvasContext: context,
    viewport: viewport,
    // 可以添加自定义注解层等
  };
  
  await page.render(renderContext).promise;
}

综合建议

1.优先尝试 vue-pdf-embed - 能满足80%的常规需求,开发效率高

2.遇到特殊需求再考虑 pdfjs-dist - 当需要:

  • 深度定制UI/交互
  • 实现复杂注解功能
  • 处理加密/特殊格式PDF
  • 需要文本提取等底层操作

3.混合使用策略

// 可以用vue-pdf-embed作为基础,配合pdfjs-dist扩展功能
import { getDocument } from 'pdfjs-dist';

// 在vue-pdf-embed之外获取文档元数据
const loadPdfMeta = async (url) => {
  const pdf = await getDocument(url).promise;
  return {
    numPages: pdf.numPages,
    metadata: await pdf.getMetadata()
  };
}

性能考量

  • 对于大型PDF文档,pdfjs-dist可能更有优势,可以手动控制内存和渲染优化
  • 对于移动端,vue-pdf-embed的封装优化通常更好
  • 服务端渲染场景,两者都需要特殊处理,但vue-pdf-embed集成更简单

最终选择应基于项目具体需求,但现代Vue项目中,vue-pdf-embed在大多数情况下都是更优选择。

对于 20MB 的大 PDF 文件,推荐使用 pdfjs-dist 而不是 vue-pdf-embed,原因如下:

为什么pdfjs-dist更适合大文件

1.更精细的加载控制

  • 可以手动实现 分页加载(懒渲染),避免一次性渲染所有页面导致卡顿。
  • 支持 渐进式渲染,先显示已加载的部分,提升用户体验。

2.内存管理更优

可以手动释放不再使用的页面内存,避免浏览器崩溃。

3.支持 Worker 多线程

PDF.js 默认使用 Web Worker 解析 PDF,避免阻塞主线程。

4.可自定义缓存策略

大文件可以分段加载(range request),减少初始等待时间。

示例代码(基于pdfjs-dist优化大文件加载)

<template>
  <div>
    <el-button @click="loadPdf">加载PDF</el-button>
    <div v-loading="loading">
      <div v-for="page in visiblePages" :key="page">
        <canvas :id="`pdf-page-${page}`"></canvas>
      </div>
    </div>
    <el-pagination
      layout="prev, pager, next"
      :total="pageCount"
      @current-change="handlePageChange"
    />
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted } from "vue";
import * as PDFJS from "pdfjs-dist";

// 设置 Worker 路径(必须!)
PDFJS.GlobalWorkerOptions.workerSrc =
  "https://cdn.jsdelivr.net/npm/pdfjs-dist@3.4.120/build/pdf.worker.min.js";

const pdfUrl = "https://example.com/large-file.pdf"; // 20MB PDF
const loading = ref(false);
const pdfDoc = ref<any>(null);
const pageCount = ref(0);
const visiblePages = ref<number[]>([]); // 当前可见的页(避免一次性渲染全部)

// 加载PDF文档(但不会立即渲染所有页)
const loadPdf = async () => {
  loading.value = true;
  try {
    const loadingTask = PDFJS.getDocument({
      url: pdfUrl,
      rangeChunkSize: 65536, // 分块加载(优化大文件)
    });
    pdfDoc.value = await loadingTask.promise;
    pageCount.value = pdfDoc.value.numPages;
    // 默认只加载第一页
    visiblePages.value = [1];
    await renderPage(1);
  } catch (error) {
    console.error("PDF加载失败:", error);
  } finally {
    loading.value = false;
  }
};

// 渲染单页
const renderPage = async (pageNumber: number) => {
  if (!pdfDoc.value) return;
  const page = await pdfDoc.value.getPage(pageNumber);
  const canvas = document.getElementById(`pdf-page-${pageNumber}`) as HTMLCanvasElement;
  const viewport = page.getViewport({ scale: 1.5 });
  canvas.width = viewport.width;
  canvas.height = viewport.height;
  await page.render({
    canvasContext: canvas.getContext("2d"),
    viewport,
  }).promise;
};

// 翻页时动态加载
const handlePageChange = (newPage: number) => {
  if (!visiblePages.value.includes(newPage)) {
    visiblePages.value.push(newPage);
    renderPage(newPage);
  }
};

onMounted(() => {
  loadPdf();
});
</script>

优化大文件加载的关键技术

1.rangeChunkSize

PDF.js 支持 HTTP Range Requests,可以分块加载文件,而不是一次性下载20MB。

2.分页懒渲染

只渲染用户当前查看的页面,避免内存爆炸。

3.Web Worker

解析PDF在后台线程执行,不阻塞UI。

4.卸载不可见页面

可以在页面离开视口时销毁 canvas 释放内存(需监听滚动)。

为什么不推荐vue-pdf-embed

虽然 vue-pdf-embed 更简单,但:

  • 默认会尝试渲染所有页面,大文件容易卡死。
  • 自定义优化空间有限,难以实现分页懒加载。
  • 内存控制较弱,20MB PDF 可能导致标签页崩溃。

最终建议

  • 如果 PDF < 5MB → 用 vue-pdf-embed(简单快捷)。
  • 如果 PDF > 5MB → 用 pdfjs-dist + 分页懒加载(稳定可控)。

对于你的 20MB PDFpdfjs-dist 是更可靠的选择!

到此这篇关于Vue预览PDF的两种方法比较(vue-pdf-embed与pdfjs-dist)的文章就介绍到这了,更多相关Vue预览PDF内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Vue 3 中使用 Element Plus 的 `el-table` 组件实现自适应高度

    Vue 3 中使用 Element Plus 的 `el-t

    在 Vue 3 中使用 Element Plus 的 `el-table` 组件实现自适应高度,你可以根据容器的高度动态设置表格的高度,下面通过示例代码给大家展示,感兴趣的朋友一起看看吧
    2024-12-12
  • Vue使用Echart图标插件之柱状图

    Vue使用Echart图标插件之柱状图

    这篇文章主要为大家详细介绍了Vue使用Echart图标插件之柱状图,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-04-04
  • 在vue项目中使用codemirror插件实现代码编辑器功能

    在vue项目中使用codemirror插件实现代码编辑器功能

    这篇文章主要介绍了在vue项目中使用codemirror插件实现代码编辑器功能(代码高亮显示及自动提示),本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-08-08
  • vue3使用高德地图进行轨迹绘制及播放代码示例

    vue3使用高德地图进行轨迹绘制及播放代码示例

    这篇文章主要介绍了如何定义地图容器及操作按钮,使用高德地图API进行轨迹绘制及播放的方法,并强调了界面样式的重要性,高德地图API的使用需要注册获取key,并且设置了地图容器的大小,需要的朋友可以参考下
    2024-11-11
  • 利用nginx部署vue项目的全过程

    利用nginx部署vue项目的全过程

    今天要用到服务器nginx,还需要把自己的vue的项目部署到服务器上去所以就写一下记录下来,下面这篇文章主要给大家介绍了关于利用nginx部署vue项目的相关资料,需要的朋友可以参考下
    2022-03-03
  • 解决Vue开发中对话框被遮罩层挡住的问题

    解决Vue开发中对话框被遮罩层挡住的问题

    在Vue的开发中,一旦我们用到对话框,经常出现的问题是对话框被遮罩层挡住,怎么来解决这个问题呢?下面小编给大家带来了Vue开发中对话框被遮罩层挡住的问题及解决方法,一起看看吧
    2018-11-11
  • vue2实现带有阻尼下拉加载的功能

    vue2实现带有阻尼下拉加载的功能

    这篇文章主要为大家介绍了vue2实现带有阻尼下拉加载的功能示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-02-02
  • vue 通过下拉框组件学习vue中的父子通讯

    vue 通过下拉框组件学习vue中的父子通讯

    这篇文章主要介绍了vue 通过下拉框组件学习vue中的父子通讯的相关知识,文中涉及到了父组件,子组件的实现代码,需要的朋友可以参考下
    2017-12-12
  • 彻底揭秘keep-alive原理(小结)

    彻底揭秘keep-alive原理(小结)

    这篇文章主要介绍了彻底揭秘keep-alive原理(小结),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-05-05
  • TypeScript基本类型 typeof 和keyof案例详解

    TypeScript基本类型 typeof 和keyof案例详解

    这篇文章主要介绍了TypeScript基本类型 typeof 和keyof案例详解,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-10-10

最新评论