星河漫步者 發表於 2026-1-12 10:45:38

Vue3+TypeScript项目中安装PDF.js详细的步骤

<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li><a href="#_label0">1. 安装 pdfjs-dist</a></li><li><a href="#_label1">2. 安装类型声明文件(TypeScript 支持)</a></li><li><a href="#_label2">3. 基础使用示例</a></li><ul class="second_class_ul"><li><a href="#_lab2_2_0">选项 1:直接使用(简单场景)</a></li><li><a href="#_lab2_2_1">选项 2:使用 Worker(推荐用于生产)</a></li></ul><li><a href="#_label3">4. 创建可复用的 PDF 查看器组件</a></li><ul class="second_class_ul"><li><a href="#_lab2_3_2">PDFViewer.vue</a></li></ul><li><a href="#_label4">5. 使用组件</a></li><ul class="second_class_ul"></ul><li><a href="#_label5">注意事项</a></li><ul class="second_class_ul"></ul><li><a href="#_label6">总结</a></li><ul class="second_class_ul"></ul></ul></div><p>在 Vue 3 + TypeScript 项目中安装和使用 pdfjs-dist(PDF.js),以下是详细的步骤:</p>
<p class="maodian"><a name="_label0"></a></p><h2>1. 安装 pdfjs-dist</h2>
<p>bash</p>
<div class="jb51code"><pre class="brush:ps;">npm install pdfjs-dist
# 或者
yarn add pdfjs-dist
# 或者
pnpm add pdfjs-dist</pre></div>
<p class="maodian"><a name="_label1"></a></p><h2>2. 安装类型声明文件(TypeScript 支持)</h2>
<p>bash</p>
<div class="jb51code"><pre class="brush:ps;">npm install @types/pdfjs-dist
# 或(新版本可能需要)
npm install --save-dev @types/pdfjs-dist</pre></div>
<p class="maodian"><a name="_label2"></a></p><h2>3. 基础使用示例</h2>
<p class="maodian"><a name="_lab2_2_0"></a></p><h3>选项 1:直接使用(简单场景)</h3>
<p>vue</p>
<div class="jb51code"><pre class="brush:js;">&lt;template&gt;
&lt;div&gt;
    &lt;canvas ref="canvasRef"&gt;&lt;/canvas&gt;
&lt;/div&gt;
&lt;/template&gt;

&lt;script setup lang="ts"&gt;
import { ref, onMounted } from 'vue'
import * as pdfjsLib from 'pdfjs-dist'

// 设置 worker
pdfjsLib.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjsLib.version}/pdf.worker.min.js`

const canvasRef = ref&lt;HTMLCanvasElement | null&gt;(null)

onMounted(async () =&gt; {
// 加载 PDF
const loadingTask = pdfjsLib.getDocument('/path/to/your.pdf')
const pdf = await loadingTask.promise

// 获取第一页
const page = await pdf.getPage(1)

// 设置缩放
const scale = 1.5
const viewport = page.getViewport({ scale })

// 渲染到 canvas
const canvas = canvasRef.value
if (!canvas) return

const context = canvas.getContext('2d')
canvas.height = viewport.height
canvas.width = viewport.width

const renderContext = {
    canvasContext: context,
    viewport: viewport
}

await page.render(renderContext).promise
})
&lt;/script&gt;</pre></div>
<p class="maodian"><a name="_lab2_2_1"></a></p><h3>选项 2:使用 Worker(推荐用于生产)</h3>
<p>vue</p>
<div class="jb51code"><pre class="brush:js;">&lt;template&gt;
&lt;div&gt;
    &lt;canvas ref="canvasRef"&gt;&lt;/canvas&gt;
    &lt;div v-if="pageCount"&gt;总页数: {{ pageCount }}&lt;/div&gt;
&lt;/div&gt;
&lt;/template&gt;

&lt;script setup lang="ts"&gt;
import { ref, onMounted } from 'vue'
import * as pdfjsLib from 'pdfjs-dist'
import type { PDFDocumentProxy } from 'pdfjs-dist/types/src/display/api'

// 使用 worker
pdfjsLib.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjsLib.version}/pdf.worker.min.js`
// 或者使用本地 worker
// pdfjsLib.GlobalWorkerOptions.workerSrc = new URL(
//   'pdfjs-dist/build/pdf.worker.min.js',
//   import.meta.url
// ).toString()

const canvasRef = ref&lt;HTMLCanvasElement | null&gt;(null)
const pageCount = ref&lt;number&gt;(0)

// 渲染 PDF 页面
const renderPage = async (pdf: PDFDocumentProxy, pageNum: number) =&gt; {
const page = await pdf.getPage(pageNum)
const scale = 1.5
const viewport = page.getViewport({ scale })

const canvas = canvasRef.value
if (!canvas) return

const context = canvas.getContext('2d')
canvas.height = viewport.height
canvas.width = viewport.width

const renderContext = {
    canvasContext: context,
    viewport: viewport
}

await page.render(renderContext).promise
}

// 加载 PDF
const loadPDF = async (url: string) =&gt; {
try {
    const loadingTask = pdfjsLib.getDocument(url)
    const pdf = await loadingTask.promise
   
    pageCount.value = pdf.numPages
    await renderPage(pdf, 1)
   
    return pdf
} catch (error) {
    console.error('Error loading PDF:', error)
    throw error
}
}

onMounted(() =&gt; {
// 加载 PDF
loadPDF('/path/to/your.pdf')
})
&lt;/script&gt;</pre></div>
<p class="maodian"><a name="_label3"></a></p><h2>4. 创建可复用的 PDF 查看器组件</h2>
<p class="maodian"><a name="_lab2_3_2"></a></p><h3>PDFViewer.vue</h3>
<p>vue</p>
<div class="jb51code"><pre class="brush:js;">&lt;template&gt;
&lt;div class="pdf-viewer"&gt;
    &lt;div class="toolbar"&gt;
      &lt;button @click="prevPage" :disabled="currentPage &lt;= 1"&gt;上一页&lt;/button&gt;
      &lt;span&gt;第 {{ currentPage }} 页 / 共 {{ totalPages }} 页&lt;/span&gt;
      &lt;button @click="nextPage" :disabled="currentPage &gt;= totalPages"&gt;下一页&lt;/button&gt;
      &lt;input
      type="number"
      v-model.number="inputPage"
      @change="goToPage"
      min="1"
      :max="totalPages"
      &gt;
      &lt;button @click="zoomIn"&gt;放大&lt;/button&gt;
      &lt;button @click="zoomOut"&gt;缩小&lt;/button&gt;
    &lt;/div&gt;
    &lt;div class="pdf-container"&gt;
      &lt;canvas ref="canvasRef"&gt;&lt;/canvas&gt;
    &lt;/div&gt;
&lt;/div&gt;
&lt;/template&gt;

&lt;script setup lang="ts"&gt;
import { ref, onMounted, watch } from 'vue'
import * as pdfjsLib from 'pdfjs-dist'
import type { PDFDocumentProxy } from 'pdfjs-dist/types/src/display/api'

interface Props {
src: string
}

const props = defineProps&lt;Props&gt;()

const canvasRef = ref&lt;HTMLCanvasElement | null&gt;(null)
const currentPage = ref(1)
const totalPages = ref(0)
const inputPage = ref(1)
const scale = ref(1.5)
let pdfInstance: PDFDocumentProxy | null = null

// 配置 worker
pdfjsLib.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjsLib.version}/pdf.worker.min.js`

// 渲染当前页
const renderCurrentPage = async () =&gt; {
if (!pdfInstance || !canvasRef.value) return

const page = await pdfInstance.getPage(currentPage.value)
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
}

// 加载 PDF
const loadPDF = async () =&gt; {
try {
    const loadingTask = pdfjsLib.getDocument(props.src)
    pdfInstance = await loadingTask.promise
    totalPages.value = pdfInstance.numPages
    currentPage.value = 1
    inputPage.value = 1
    await renderCurrentPage()
} catch (error) {
    console.error('Failed to load PDF:', error)
}
}

// 导航方法
const prevPage = () =&gt; {
if (currentPage.value &gt; 1) {
    currentPage.value--
    inputPage.value = currentPage.value
}
}

const nextPage = () =&gt; {
if (pdfInstance &amp;&amp; currentPage.value &lt; pdfInstance.numPages) {
    currentPage.value++
    inputPage.value = currentPage.value
}
}

const goToPage = () =&gt; {
if (pdfInstance) {
    const pageNum = Math.max(1, Math.min(inputPage.value, pdfInstance.numPages))
    currentPage.value = pageNum
    inputPage.value = pageNum
}
}

const zoomIn = () =&gt; {
scale.value += 0.25
}

const zoomOut = () =&gt; {
scale.value = Math.max(0.5, scale.value - 0.25)
}

// 监听页面变化
watch(currentPage, renderCurrentPage)
watch(scale, renderCurrentPage)

// 监听 PDF 源变化
watch(() =&gt; props.src, loadPDF)

onMounted(loadPDF)
&lt;/script&gt;

&lt;style scoped&gt;
.pdf-viewer {
width: 100%;
height: 100%;
}

.toolbar {
display: flex;
gap: 10px;
padding: 10px;
background: #f5f5f5;
align-items: center;
}

.pdf-container {
overflow: auto;
padding: 20px;
}

canvas {
border: 1px solid #ddd;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
&lt;/style&gt;</pre></div>
<p class="maodian"><a name="_label4"></a></p><h2>5. 使用组件</h2>
<p>vue</p>
<div class="jb51code"><pre class="brush:xhtml;">&lt;template&gt;
&lt;div&gt;
    &lt;PDFViewer src="/path/to/document.pdf" /&gt;
&lt;/div&gt;
&lt;/template&gt;

&lt;script setup lang="ts"&gt;
import PDFViewer from './components/PDFViewer.vue'
&lt;/script&gt;</pre></div>
<p class="maodian"><a name="_label5"></a></p><h2>注意事项</h2>
<ul><li><p><strong>Worker 配置</strong>:生产环境中建议使用 worker 提高性能</p></li><li><p><strong>版本兼容性</strong>:确保 pdfjs-dist 和 @types/pdfjs-dist 版本兼容</p></li><li><p><strong>CDN 或本地</strong>:可以选择使用 CDN 或本地 worker 文件</p></li><li><p><strong>内存管理</strong>:大型 PDF 注意内存管理,及时清理资源</p></li><li><p><strong>错误处理</strong>:添加适当的错误处理机制</p></li></ul>
<p>这样你就可以在 Vue 3 + TypeScript 项目中成功使用 PDF.js 了!</p>
<p class="maodian"><a name="_label6"></a></p><h2>总结</h2>
頁: [1]
查看完整版本: Vue3+TypeScript项目中安装PDF.js详细的步骤