Code前端首页关于Code前端联系我们

先搞懂,你的Vue3项目真的需要集成在线Office吗?

terry 53分钟前 阅读数 7 #Vue
文章标签 Vue3在线Office集成

最近不少做Vue3后台、文档管理系统的朋友来问,手上要加个不用跳转到第三方云盘的在线Office预览/改点错别字的功能,试了几个开源库要么版本不兼容Vue3 Composition API,要么加载慢、样式乱,还有找不到靠谱中文文档的情况——今天就来唠唠这个事儿,从场景适配到工具推荐,再到具体的Composition API写法,一步步说清楚。 别看到“在线Office”就觉得酷,先掰扯掰扯自己的实际需求,选错方向反而耽误事儿。

如果有这些场景,那集成确实是刚需: 比如做企业内部文档库,文件存放在公司私有服务器或指定OSS上,不能随便给第三方平台链接权限,得在自己的Vue3页面里带水印、限制下载/打印/复制直接看; 比如做OA审批流,附件(合同草稿、报销单Excel)需要审批人直接在页面预览关键内容,不用保存到本地; 比如做在线教育的作业批改,学生提交的Word/PDF作业要在旁边打勾打叉加几句文字批注,轻量够用就行; 比如做电商的产品参数上传后台,运营提交Excel后可以直接预览校验格式,避免上传错数据类型。

但如果是这几种情况,就别折腾集成了: 只是偶尔给用户一个下载链接,没必要在线占带宽; 预算充足,直接买成熟的第三方在线Office嵌入版(比如腾讯文档企业版、飞书文档开放平台),人家的兼容性、稳定性、功能全是现成的; 只需要处理纯文本、简单的单页PDF,用vue-pdf-next这种轻量PDF库或者直接转markdown渲染更省事儿。

接下来选工具:Vue3适配好的在线Office方案有哪些? 目前主流的方案分两类,一类是基于WebAssembly纯前端渲染的(不用后端转格式,数据不离开浏览器),另一类是基于微软Office Online Server(WOS)或开源替代方案的后端转+前端渲染(兼容性最好,但需要自己搭后端服务)。

先说说纯前端的首选——OnlyOffice Document Builder的轻量前端SDK,或者更精准的说法是它的Vue3封装库@onlyoffice/vue-documentserver(哦不对,还有一个更轻的纯前端社区封装?等下查一下,是叫vue-office对吧?对,这个是国内做的Vue3适配Vue2都有的纯前端Office预览库,用的是sheetjs+xlsx-populate处理Excel,pdfjs-dist处理PDF,docx-preview处理Word/PPT,都是社区顶流的WebAssembly库组合,而且完全开源免费、不用搭后端、不用申请任何密钥,直接npm install就能用,对新手和轻量场景特别友好。

那纯前端的缺点是什么?就是PPT预览的效果可能不如原生Office或者WOS,动画、复杂的SmartArt、3D模型这些大概率显示不出来,Excel的宏肯定不能用,轻量编辑(Word改字、Excel改单元格内容、PDF加文字批注)部分,目前只有Word和Excel有初步的社区支持,PDF的话可以结合pdfjs-dist自己加个简单的文本输入框,但没那么顺手。

如果你的场景对兼容性要求极高,比如必须完美显示PPT动画、Word的水印复杂排版、Excel的函数实时计算,那只能选后端转+前端渲染的方案,国内常用的是OnlyOffice Document Server(这个是完全开源的,有社区版和企业版,社区版免费但用户数有限制,企业版收费但功能全,有技术支持),还有微软的WOS,但WOS需要购买Windows Server和Office授权,成本很高,一般只有大型企业才会用。

那后端转+前端渲染的缺点是什么?就是需要自己搭后端服务,社区版的OnlyOffice Document Server还得自己维护,而且如果你的文件比较大,转格式的时间会比较长,需要加个loading动画过渡一下,数据会传到OnlyOffice Document Server处理(当然你可以把OnlyOffice Document Server和你的Vue3项目、文件存储服务器放在同一个内网,数据不会外泄)。

纯前端轻量方案实战:用vue-office在Vue3项目里快速预览和编辑Word/Excel/PDF 刚才说了,轻量场景下vue-office是首选,那接下来就说具体的Composition API写法,用的是Vue3+vite+TypeScript的标准项目结构,没有TS的朋友直接把类型声明删掉就行。

首先安装依赖: 打开终端,进入你的Vue3项目根目录,执行npm install @vue-office/docx @vue-office/excel @vue-office/pdf vue-demi命令就行,vue-demi是用来兼容Vue2和Vue3的,不管你用哪个版本都要装。

然后配置vite.config.ts(或者vite.config.js),因为vue-office用到了WebAssembly文件,vite默认不会打包这些文件,所以需要加个配置项: 在defineConfig的plugins下面?不对,是在assetsInclude里,加上['*.wasm'],这样vite打包的时候就会把WebAssembly文件当成静态资源处理,不会报错。

接下来写预览和轻编辑的组件,咱们做一个可以切换文件类型的组件,比如上传或者输入文件URL后,选择Word/Excel/PDF,然后显示预览和简单的编辑按钮。

首先导入需要的库和组件: import { ref, computed } from 'vue' import VueOfficeDocx from '@vue-office/docx' import VueOfficeExcel from '@vue-office/excel' import VueOfficePdf from '@vue-office/pdf' import '@vue-office/docx/lib/index.css' import '@vue-office/excel/lib/index.css' import '@vue-office/pdf/lib/index.css'

然后定义响应式数据: // 文件类型,默认是Word const fileType = ref<'docx' | 'xlsx' | 'pdf'>('docx') // 文件URL或者ArrayBuffer/Blob,支持这三种格式 const fileData = ref<string | ArrayBuffer | Blob>('') // 是否开启轻量编辑,只有Word和Excel支持,PDF不支持 const editable = ref(false)

然后定义计算属性,根据文件类型返回对应的组件: const currentComponent = computed(() => { switch (fileType.value) { case 'docx': return VueOfficeDocx case 'xlsx': return VueOfficeExcel case 'pdf': return VueOfficePdf default: return VueOfficeDocx } })

然后定义上传文件的方法,这里用的是原生的input type="file",也可以用element-plus或者ant-design-vue的上传组件: const handleFileChange = (e: Event) => { const target = e.target as HTMLInputElement const file = target.files?.[0] if (!file) return // 根据文件名后缀判断文件类型 const suffix = file.name.split('.').pop()?.toLowerCase() if (suffix) { if (['doc', 'docx'].includes(suffix)) { fileType.value = 'docx' } else if (['xls', 'xlsx'].includes(suffix)) { fileType.value = 'xlsx' } else if (suffix === 'pdf') { fileType.value = 'pdf' } else { alert('只支持Word、Excel、PDF文件') return } } // 把File对象转成ArrayBuffer const reader = new FileReader() reader.onload = (e) => { fileData.value = e.target?.result as ArrayBuffer } reader.readAsArrayBuffer(file) }

然后定义轻量编辑保存的方法,这里只做一个简单的console.log,实际项目里可以把ArrayBuffer转成Blob,然后上传到OSS或者私有服务器: const handleSave = () => { if (fileType.value === 'pdf') { alert('PDF不支持轻量编辑') return } // 获取编辑后的ArrayBuffer,Word和Excel的获取方法不一样 if (fileType.value === 'docx') { const docxComponent = document.querySelector('.vue-office-docx') as any const editedArrayBuffer = docxComponent.getContent() console.log('编辑后的Word ArrayBuffer:', editedArrayBuffer) // 这里可以把editedArrayBuffer转成Blob上传 } else if (fileType.value === 'xlsx') { const excelComponent = document.querySelector('.vue-office-excel') as any const editedArrayBuffer = excelComponent.getContent() console.log('编辑后的Excel ArrayBuffer:', editedArrayBuffer) // 这里可以把editedArrayBuffer转成Blob上传 } }

然后写模板:

最后写一点简单的样式,让界面好看一点:

这样一个可以切换文件类型、上传文件、轻量编辑保存的Vue3在线Office组件就做好了,是不是很简单?

写在最后:纯前端方案的优化建议 刚才的组件已经能用了,但如果你的项目文件比较大,或者用户体验要求比较高,可以做以下几点优化:

  1. 给预览区域加个loading动画,因为大文件的WebAssembly加载和渲染需要一点时间;
  2. 针对不同的文件大小做个提示,比如超过10MB的Excel文件,告诉用户可能会加载慢;
  3. 如果你的文件存放在OSS上,记得配置CORS,不然会出现跨域错误,无法加载文件;
  4. 可以结合element-plus或者ant-design-vue的上传组件,支持拖拽上传、批量上传、进度条显示等功能;
  5. 如果需要给Word/Excel/PDF加水印,可以用canvas或者第三方库(比如watermark-dom)自己加,也可以用OnlyOffice Document Server的水印功能。

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

热门