亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Vue3實(shí)現(xiàn)PDF文件解析與預(yù)覽的完整實(shí)踐

 更新時(shí)間:2025年06月17日 09:10:27   作者:黑土豆  
在實(shí)際的前端開發(fā)中,經(jīng)常會碰到需要在線預(yù)覽PDF文件的場景,比如后臺管理系統(tǒng)查看合同、教育平臺展示試卷、審批系統(tǒng)預(yù)覽發(fā)票等等,所以本文給大家介紹了Vue3實(shí)現(xiàn)PDF文件解析與預(yù)覽的完整實(shí)踐,需要的朋友可以參考下

前言

在實(shí)際的前端開發(fā)中,經(jīng)常會碰到需要在線預(yù)覽PDF文件的場景,比如后臺管理系統(tǒng)查看合同、教育平臺展示試卷、審批系統(tǒng)預(yù)覽發(fā)票等等。這類需求的核心目標(biāo)就是:用戶不需要下載,就能直接在頁面中查看 PDF 文檔內(nèi)容

最近,我在公司的Vue3項(xiàng)目中剛好負(fù)責(zé)了一塊PDF預(yù)覽功能的開發(fā),趁熱打鐵把這塊功能的實(shí)現(xiàn)過程整理出來,希望能幫到有類似需求的朋友。

常見的 PDF 文件預(yù)覽方式有哪些?

在查閱了一些資料,也踩了幾個(gè)坑之后,我發(fā)現(xiàn)目前主流的三種方式大概如下:

實(shí)現(xiàn)方式簡介優(yōu)點(diǎn)缺點(diǎn)
iframe / embed 標(biāo)簽直接嵌入瀏覽器內(nèi)核的渲染功能簡單,不需要引入額外依賴樣式和交互無法自定義,兼容性差
PDF.js(pdfjs-dist)由 Mozilla 出品的開源 PDF 渲染器,支持 canvas / svg 渲染功能強(qiáng)大,完全前端渲染,可高度定制實(shí)現(xiàn)略復(fù)雜,需要自己處理分頁、縮放等邏輯
后端轉(zhuǎn)圖片將 PDF 轉(zhuǎn)成圖片給前端展示前端負(fù)擔(dān)小,兼容性好沒有文字層,不能選中、搜索、復(fù)制文字,服務(wù)端壓力大

我最終選用的是 PDF.js(pdfjs-dist),原因很簡單:其由 Mozilla 維護(hù),穩(wěn)定性強(qiáng),功能完善,支持多頁分頁、縮放、搜索、高亮等能力。還有就是需求需要的是可以交互、可以選中文本的預(yù)覽組件,而且盡量不依賴后端處理。

開始動(dòng)手:安裝并配置 pdfjs-dist

先安裝它:

npm install pdfjs-dist

然后,在我們自己的工具函數(shù)里,引入并配置好Web Worker路徑(為了性能,PDF.js會用 worker異步解析):

import * as pdfjsLib from 'pdfjs-dist/build/pdf.mjs'

pdfjsLib.GlobalWorkerOptions.workerSrc = `https://cdn.jsdelivr.net/npm/pdfjs-dist@${(pdfjsLib as any).version}/build/pdf.worker.mjs`

注意:如果你用的是Vite,pdfjsworker不好自動(dòng)打包,用CDN路徑是目前最穩(wěn)妥的方式。當(dāng)然你也可以自行下載后配置本地路徑。

核心功能封裝:純 JS 函數(shù)渲染PDF到DOM中

以下是我封裝好的一個(gè)核心函數(shù),接收PDF文件地址和容器DOM,然后渲染出完整PDF頁內(nèi)容。

// utils/pdfRenderer.ts
import * as pdfjsLib from 'pdfjs-dist/build/pdf.mjs'

pdfjsLib.GlobalWorkerOptions.workerSrc = `https://cdn.jsdelivr.net/npm/pdfjs-dist@${(pdfjsLib as any).version}/build/pdf.worker.mjs`

interface RenderPdfOptions {
  scale?: number
  page?: number
}

export async function renderPdfToContainer(
  container: HTMLElement,
  url: string,
  options?: RenderPdfOptions
) {
  container.innerHTML = ''

  const scale = options?.scale ?? 1.5
  const targetPage = options?.page

  try {
    const loadingTask = pdfjsLib.getDocument(url)
    const pdf = await loadingTask.promise

    const pages = targetPage
      ? [targetPage]
      : Array.from({ length: pdf.numPages }, (_, i) => i + 1)

    for (const pageNum of pages) {
      const page = await pdf.getPage(pageNum)
      const viewport = page.getViewport({ scale })

      const canvas = document.createElement('canvas')
      const context = canvas.getContext('2d')
      if (!context) continue

      canvas.width = viewport.width
      canvas.height = viewport.height
      container.appendChild(canvas)

      const renderContext = {
        canvasContext: context,
        viewport
      }

      await page.render(renderContext).promise
    }
  } catch (error) {
    console.error('PDF 加載失敗:', error)
    container.innerHTML = '<p style="color:red">加載失敗,請檢查文件格式或地址是否正確。</p>'
  }
}

在 Vue3 組件中如何使用?

Vue3項(xiàng)目中寫了一個(gè)簡單組件,效果就是加載PDF文件并將其渲染到頁面中:

<template>
  <div ref="pdfWrapper" class="pdf-container" />
</template>

<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { renderPdfToContainer } from '@/utils/pdfRenderer'

const pdfWrapper = ref<HTMLElement>()
const pdfUrl = '/files/sample.pdf' // 替換成你的文件地址

onMounted(() => {
  if (pdfWrapper.value) {
    renderPdfToContainer(pdfWrapper.value, pdfUrl, { scale: 1.25 })
  }
})
</script>

<style scoped>
.pdf-container {
  width: 100%;
  overflow: auto;
  background: #f6f6f6;
  padding: 16px;
}
</style>

小提醒:為了避免渲染異常,renderPdfToContainer 必須在 onMounted 后 DOM 掛載后調(diào)用。

遇到的問題和一些解決方案

這里是開發(fā)過程中真實(shí)踩過的幾個(gè)坑,順手整理一下,希望你少走彎路。

問題一:加載失敗,控制臺報(bào)錯(cuò) “Unexpected token '<'…”

原因PDF地址可能不對,返回的不是PDF,而是HTML錯(cuò)誤頁。 解決方式

  • 檢查地址是不是404
  • fetch(url)看看實(shí)際返回內(nèi)容是不是PDF

問題二:PDF渲染模糊,不清晰

原因canvas分辨率低或者devicePixelRatio沒處理。 優(yōu)化方法

const dpr = window.devicePixelRatio || 1
canvas.width = viewport.width * dpr
canvas.height = viewport.height * dpr
canvas.style.width = `${viewport.width}px`
canvas.style.height = `${viewport.height}px`
context.setTransform(dpr, 0, 0, dpr, 0, 0)

這樣處理后,高清屏下也能展示得更清晰。

問題三:只想加載某一頁怎么辦?

直接傳 page 參數(shù):

renderPdfToContainer(dom, url, { page: 1 })

我自己在做分頁加載的時(shí)候也用到了這個(gè)邏輯。

問題四:怎么支持本地文件預(yù)覽(用戶上傳后立即預(yù)覽)?

const reader = new FileReader()
reader.onload = async () => {
  const typedArray = new Uint8Array(reader.result as ArrayBuffer)
  const pdf = await pdfjsLib.getDocument({ data: typedArray }).promise
  // 同樣調(diào)用 page.render 即可渲染
}
reader.readAsArrayBuffer(file)

這個(gè)寫法可以用在 <input type="file"> 的上傳場景。

小結(jié)一下

整個(gè)PDF文件解析功能,其實(shí)可以拆成三步:

  • 引入pdfjs-dist并設(shè)置好worker
  • 封裝一個(gè)renderPdfToContainer函數(shù)做PDF渲染
  • Vue3項(xiàng)目中按需調(diào)用

整個(gè)過程其實(shí)不復(fù)雜,但很多資料都散著,或者講得太官方,不太實(shí)用。我這次是花了些時(shí)間整理,并親自踩坑測試的,如果你也有這類需求,希望這篇文章能讓你少走幾步彎路。

結(jié)語

Vue3項(xiàng)目中實(shí)現(xiàn)PDF預(yù)覽并不難,但要實(shí)現(xiàn) 高性能、強(qiáng)交互、低資源占用 的用戶體驗(yàn),需要我們不斷抽象渲染邏輯、優(yōu)化性能瓶頸并兼顧跨平臺適配。希望本文能幫助你快速掌握在Vue3中集成PDF.js的實(shí)戰(zhàn)方案。

以上就是Vue3實(shí)現(xiàn)PDF文件解析與預(yù)覽的完整實(shí)踐的詳細(xì)內(nèi)容,更多關(guān)于Vue3 PDF解析與預(yù)覽的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • vue a標(biāo)簽點(diǎn)擊實(shí)現(xiàn)賦值方式

    vue a標(biāo)簽點(diǎn)擊實(shí)現(xiàn)賦值方式

    這篇文章主要介紹了vue a標(biāo)簽點(diǎn)擊實(shí)現(xiàn)賦值方式,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • 全新打包工具parcel零配置vue開發(fā)腳手架

    全新打包工具parcel零配置vue開發(fā)腳手架

    parcel-vue 一個(gè)基于Parcel打包工具的 VueJS急速開發(fā)腳手架解決方案,強(qiáng)烈建議使用node8.0以上。下面通過本文給大家介紹全新打包工具parcel零配置vue開發(fā)腳手架的相關(guān)知識,感興趣的朋友一起看看吧
    2018-01-01
  • ant-design-vue按需加載的坑的解決

    ant-design-vue按需加載的坑的解決

    這篇文章主要介紹了ant-design-vue按需加載的坑的解決,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-05-05
  • vue中動(dòng)態(tài)select的使用方法示例

    vue中動(dòng)態(tài)select的使用方法示例

    這篇文章主要介紹了vue中動(dòng)態(tài)select的使用方法,結(jié)合實(shí)例形式分析了vue.js使用動(dòng)態(tài)select創(chuàng)建下拉菜單相關(guān)實(shí)現(xiàn)技巧與操作注意事項(xiàng),需要的朋友可以參考下
    2019-10-10
  • 一篇文章總結(jié)Vue3.2語法糖使用

    一篇文章總結(jié)Vue3.2語法糖使用

    Vue3.2(21年8月10日)相比于Vue3新增了語法糖,減少了代碼冗余,下面這篇文章主要給大家介紹了關(guān)于Vue3.2語法糖使用的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-11-11
  • vue使用swiper實(shí)現(xiàn)中間大兩邊小的輪播圖效果

    vue使用swiper實(shí)現(xiàn)中間大兩邊小的輪播圖效果

    這篇文章主要介紹了vue使用swiper實(shí)現(xiàn)中間大兩邊小的輪播圖效果,本文分步驟通過實(shí)例代碼講解的非常詳細(xì),需要的朋友可以參考下
    2019-11-11
  • 對VUE中的對象添加屬性

    對VUE中的對象添加屬性

    今天小編就為大家分享一篇對VUE中的對象添加屬性,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-09-09
  • vue.js實(shí)現(xiàn)只彈一次彈框

    vue.js實(shí)現(xiàn)只彈一次彈框

    本篇文章通過代碼實(shí)例給大家詳細(xì)講述了一個(gè)vue的實(shí)例,實(shí)現(xiàn)只彈一次彈框功能,一起學(xué)習(xí)分享下。
    2018-01-01
  • vue3點(diǎn)擊出現(xiàn)彈窗后背景變暗且不可操作的實(shí)現(xiàn)代碼

    vue3點(diǎn)擊出現(xiàn)彈窗后背景變暗且不可操作的實(shí)現(xiàn)代碼

    這篇文章主要介紹了vue3點(diǎn)擊出現(xiàn)彈窗后背景變暗且不可操作的實(shí)現(xiàn)代碼,本文通過實(shí)例代碼圖文相結(jié)合給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-08-08
  • vue中watch的實(shí)際開發(fā)學(xué)習(xí)筆記

    vue中watch的實(shí)際開發(fā)學(xué)習(xí)筆記

    watch是Vue實(shí)例的一個(gè)屬性是用來響應(yīng)數(shù)據(jù)的變化,需要在數(shù)據(jù)變化時(shí)執(zhí)行異步或開銷較大的操作時(shí),這個(gè)方式是最有用的,下面這篇文章主要給大家介紹了關(guān)于vue中watch的實(shí)際開發(fā)筆記,需要的朋友可以參考下
    2022-11-11

最新評論