夜雨聆风学习资料网

ARTICLE · 1331793

PDF.js 淘汰!Vue3 工具爆火!统一 pdf excel docx!

PDF.js 淘汰!Vue3 工具爆火!统一 pdf excel docx!

后台管理系统做久了,就会发现一个很烦人的需求:文件预览。

PDF 要接 PDF.js,Excel 要处理表格,Word 又得找一套文档预览方案。项目里装了一堆依赖,页面还没写多少,光是文件预览就折腾出好几套实现。

更麻烦的是,业务页面根本不关心文件内部怎么解析。用户点开一个附件,只想看内容,至于它是 PDF、Excel 还是 DOCX,最好由组件自己处理。

最近 Vue3 生态里有一类统一文件预览工具,思路就是把这些格式收进同一个组件。这里要注意,并不是 PDF.js 被彻底淘汰了,而是没必要再让业务页面直接维护每一种文件格式的预览逻辑。 PDF.js 仍然可以作为底层 PDF 渲染引擎。

假设后台有个合同管理页面,附件可能是 PDF 合同、Excel 报价单,也可能是 Word 版的说明文档。

以前的做法通常是:

  • PDF:单独写 PDF 预览组件。
  • Excel:读取工作簿,再自己渲染表格。
  • DOCX:引入文档解析库,处理段落、表格和样式。

这几套代码分散在不同页面,后面要加一个文件格式,又得改一轮。

如果选用支持 Vue3 的统一预览组件,业务层只需要负责两件事:拿到文件地址,把文件交给预览组件。

比如可以把调用入口统一成这样:

<script setup>
import { ref } from 'vue'
import FilePreview from '@/components/FilePreview.vue'

const currentFile = ref({
  name: '报价单.xlsx',
  url: '/api/files/quotation.xlsx'
})

function openAttachment(file) {
  currentFile.value = file
}
</script>

<template>
  <FilePreview
    v-if="currentFile"
    :src="currentFile.url"
    :file-name="currentFile.name"
  />
</template>

这里的 FilePreview 是业务层的统一组件接口示例,并非某个具体开源项目的原生 API。实际使用时,需要按所选工具的组件名称和参数调整。

这样改完,合同列表、订单详情、审批记录都可以复用同一个入口。业务页面不用再判断 PDF 怎么加载、Excel 怎么解析,后续维护也清爽不少。

不过,别急着把所有文件都往组件里塞。统一的是调用方式,不代表所有文件的解析方式都一样。

不同格式的文件,处理方式差别很大。

PDF 关注分页、缩放、文本选择和页面渲染;Excel 需要解析工作表、单元格、合并区域;DOCX 则涉及段落、表格、图片和样式。

统一预览工具通常是在外层做格式识别,再调用相应的解析或渲染能力。

举个例子,下面这段代码就是一个简单的格式分发逻辑。不是完整的预览引擎,但足以说明组件内部应该怎么组织。

const previewHandlers = {
  pdf: renderPdf,
  xlsx: renderExcel,
  xls: renderExcel,
  docx: renderDocx
}

function getFileType(fileName) {
  const index = fileName.lastIndexOf('.')

return index < 0
    ? ''
    : fileName.slice(index + 1).toLowerCase()
}

async function previewFile(file) {
  const type = getFileType(file.name)
  const handler = previewHandlers[type]

if (!handler) {
    throw new Error(`暂不支持预览该文件:${type || '未知格式'}`)
  }

return handler(file.url)
}

其中的 renderPdf、renderExcel 和 renderDocx 需要由具体的解析库实现。

这种写法有个好处:以后增加 CSV、PPTX 等格式,不用在每个业务页面里堆一串 if...else,只需要扩展对应的处理器。

当然,支持多少种格式、是否支持分页和复杂样式,还是要看具体工具,不能只看宣传页上的格式列表。

本地拿几个小文件测试,通常看不出什么问题。上线后,文件预览可能会遇到跨域、鉴权、内存占用和大文件加载等麻烦。

尤其是企业内部系统,文件地址经常不是一个可以直接访问的静态 URL,而是需要携带登录凭证的接口。

比如下面这种情况:

async function loadPreviewFile(url) {
  const response = await fetch(url, {
    credentials: 'include'
  })

if (!response.ok) {
    throw new Error(`文件加载失败:HTTP ${response.status}`)
  }

  const blob = await response.blob()

return URL.createObjectURL(blob)
}

这段代码适合需要通过 Cookie 鉴权获取文件的场景,但也有代价:blob() 通常要先把整个响应读入内存。碰上几百 MB 的 PDF,就不能想当然地这么处理了。

大文件预览更适合考虑 HTTP Range 分段请求、按页加载等能力。使用哪种方式,要看底层预览库是否支持,以及服务端有没有正确处理 Range 请求。

还有一个细节:通过 URL.createObjectURL() 创建的临时地址,使用完记得调用 URL.revokeObjectURL() 释放。反复打开、关闭预览页面,却一直不释放,内存占用可能会慢慢涨起来。

至于 Excel 和 Word,也别把“能够打开”当成“完全还原”。复杂公式、特殊字体、分页布局以及嵌入对象,都可能与原始 Office 软件中的显示效果不同。

如果业务要求严格还原排版,服务端转换成 PDF 往往更值得考虑。

最后再说一句,选择 Vue3 文件预览工具时,我更在意三个地方:格式支持是否真实可用、项目是否持续维护、遇到大文件时会不会拖垮浏览器。

如果只是展示 PDF,继续使用 PDF.js 完全没问题;如果一个后台同时要预览 PDF、Excel、DOCX,统一预览组件确实能减少不少重复代码。

工具可以换,底层原理还是得搞清楚。否则,开发时省下的几行代码,最后可能全变成线上排查的时间。

回首页,搜索你想要的文档

在首页搜索框输入关键词,快速定位资料

文库首页搜索指引 立即搜索

相关学习资料