Vue3實現(xiàn)常見附件的預(yù)覽功能
前言
最近開發(fā)了一個建筑相關(guān)的移動端項目,其中有各種附件預(yù)覽的功能。通過各種嘗試,總結(jié)出了一些常用的文件預(yù)覽方式。本文介紹vue3常用文件(pdf、word、excel、txt)的預(yù)覽。
一、pdf預(yù)覽
本文使用的pdf預(yù)覽是通過 pdfjs-dist 插件,在 Vue3
使用的時候還是有一些坑。
首先通過 npm
安裝插件
npm install --save pdfjs-dist
然后在頁面中引入
const PDF = require('pdfjs-dist')
啟動項目之后就會報錯如下:
仔細(xì)查看報錯信息,是插件中使用了 es11
的語法 ?.
然而當(dāng)項目啟動,插件中的代碼沒有經(jīng)過編譯,導(dǎo)致項目不能啟動。解決方案是在項目中配置webpack
針對于這個插件進(jìn)行編譯。
修改項目根目錄下 vue.config.js
,如果沒有就創(chuàng)建一個,在文件中增加如下代碼:
// vue.config.js module.exports = { // ... chainWebpack: config => { // ... config.module.rule('pdfjs-dist').test({ test: /\.js$/, include: path.join(__dirname, 'node_modules/pdfjs-dist') }).use('babel-loader').loader('babel-loader').options({ presets: ['@babel/preset-env'], plugins: ['@babel/plugin-proposal-optional-chaining'] }) } }
之后的錯誤
需要在引入 pdfjs-dist
之后配置 workerSrc
,但是引入 pdfjs-dist/build/pdf.worker.entry
之后瀏覽器還是有個警告:Warning: Setting up fake worker.
,經(jīng)過各種原因查找,最終找到了一句描述:pdf.worker.js必須位于自己的文件中(而不是與pdf.js捆綁在一起)。否則它不能在服務(wù)工作線程中運(yùn)行。
解決方式:將 pdfjs-dist/build/pdf.worker.js
復(fù)制一份放到項目 public
目錄下。
pdf解析組件代碼
通過 pdfjs-dist
加載pdf文件,獲取到總頁數(shù)將 canvas
遍歷到頁面上,然后編寫一個遞歸函數(shù)通過 getPage
解析 pdf 的每一頁將pdf內(nèi)容渲染到 canvas
。以下示例就是封裝了一個解析pdf組件,通過傳遞文件鏈接全屏渲染pdf。
<template> <div class="pdf"> <template v-for="item in pageNum" :key="item"> <canvas :id="`pdf-canvas-${item}`" class="pdf-page" /> </template> </div> </template> <script> import { reactive, toRefs, nextTick, watchEffect } from 'vue' const PDF = require('pdfjs-dist') PDF.GlobalWorkerOptions.workerSrc = '/pdf.worker.js' export default { name: 'DisplayPdf', props: { url: { type: String, default: '' } }, setup (props, { emit }) { const state = reactive({ pageNum: 0, pdfCtx: null }) watchEffect(() => { if (props.url) { resolvePdf(props.url) } }) const resolvePdf = (url) => { const loadingTask = PDF.getDocument(url) loadingTask.promise.then(pdf => { state.pdfCtx = pdf state.pageNum = pdf.numPages nextTick(() => { renderPdf() }) }) } const renderPdf = (num = 1) => { state.pdfCtx.getPage(num).then(page => { const canvas = document.getElementById(`pdf-canvas-${num}`) const ctx = canvas.getContext('2d') const viewport = page.getViewport({ scale: 1 }) // 畫布大小,默認(rèn)值是width:300px,height:150px canvas.height = viewport.height canvas.width = viewport.width // 畫布的dom大小, 設(shè)置移動端,寬度設(shè)置鋪滿整個屏幕 const clientWidth = document.body.clientWidth canvas.style.width = clientWidth + 'px' // 根據(jù)pdf每頁的寬高比例設(shè)置canvas的高度 canvas.style.height = clientWidth * (viewport.height / viewport.width) + 'px' page.render({ canvasContext: ctx, viewport }) if (num < state.pageNum) { renderPdf(num + 1) } else { emit('onRendered') } }) } return { ...toRefs(state) } } } </script>
二、txt文件預(yù)覽
txt
的文件預(yù)覽就比較簡單了,因為沒有樣式,我們直接讀取文件的內(nèi)容,展示到頁面即可。
需要注意的是,如果需要正常顯示 txt
文件中的換行符需要在文本容器上加上樣式:white-space: pre-wrap;
,或者將內(nèi)容中所有的換行符替換成 <br>
使用 v-html
顯示內(nèi)容。
<template> <div class="txt" style="white-space: pre-wrap;">{{ txtContent }}</div> </template> <script> import { ref } from 'vue' import axios from 'axios' export default { name: 'PreviewTxt', setup () { const txtContent = ref('') const url = '/demo.txt' axios.get(url, { responseType: 'text' }).then(res => { txtContent.value = res.data }) return { txtContent } } } </script>
三、word預(yù)覽
本文中使用的是 mammoth.js
,會忽略復(fù)雜樣式,只是實現(xiàn)了簡單內(nèi)容預(yù)覽,使用方式也很簡單,通過http請求獲取文件的 ArrayBuffer
,再使用 mammoth.convertToHtml
將內(nèi)容轉(zhuǎn)換成 html
。如果文件能夠外網(wǎng)訪問并且機(jī)密性不高,還是推薦使用 http://view.officeapps.live.com/op/view.aspx?src=文檔url
的方式預(yù)覽。
// npm install mammoth --save <template> <div class="word-container" v-html="doc" /> </template> <script> import { watchEffect, ref } from 'vue' import axios from 'axios' import mammoth from 'mammoth' export default { name: 'DisplayDocx', props: { url: { type: String, default: '' } }, setup (props) { const doc = ref('') const resolveDocx = async (url) => { const { data } = await axios.get(url, { responseType: 'arraybuffer' }) const res = await mammoth.convertToHtml({ arrayBuffer: data }) doc.value = res.value } watchEffect(() => { if (props.url) resolveDocx(props.url) }) return { doc } } } </script>
四、excel預(yù)覽
excel預(yù)覽是使用 xsls
插件,讀取文件的某個 Sheet
中的內(nèi)容,然后把內(nèi)容轉(zhuǎn)換成 json
我們自己用json渲染表格。
npm install xsls --save
讀取出json內(nèi)容如下,默認(rèn)以第一行為 key。
也可以通過 sheet_to_json
第二個參數(shù)改變,如果傳入 { header: 1 }
則返回每行為文件中的一行組成數(shù)組
示例代碼
import xlsx from 'xlsx' import axios from 'axios' export default { name: 'PreviewExcel', async setup () { const url = '/demo.xlsx' const { data } = await axios.get(url, { responseType: 'arraybuffer' }) const ctx = xlsx.read(data, { type: 'array' }) const result = xlsx.utils.sheet_to_json(ctx.Sheets[ctx.SheetNames[0]], { header: 1 }) console.log(result) } }
以上就是Vue3實現(xiàn)常見附件的預(yù)覽功能的詳細(xì)內(nèi)容,更多關(guān)于Vue3預(yù)覽的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Vue3實戰(zhàn)學(xué)習(xí)配置使用vue?router路由步驟示例
這篇文章主要為大家介紹了Vue3實戰(zhàn)學(xué)習(xí)配置使用vue?router路由步驟示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06利用FetchEventSource在大模型流式輸出的應(yīng)用方式
這篇文章主要介紹了利用FetchEventSource在大模型流式輸出的應(yīng)用方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-08-08詳解Element-ui NavMenu子菜單使用遞歸生成時使用報錯
這篇文章主要介紹了詳解Element-ui NavMenu子菜單使用遞歸生成時使用報錯,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04vue+ElementUI實現(xiàn)訂單頁動態(tài)添加產(chǎn)品數(shù)據(jù)效果實例代碼
本篇文章主要介紹了vue+ElementUI實現(xiàn)訂單頁動態(tài)添加產(chǎn)品效果實例代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-07-07在vue中created、mounted等方法使用小結(jié)
這篇文章主要介紹了在vue中created、mounted等方法使用小結(jié),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-07-07vue+vuecli+webpack中使用mockjs模擬后端數(shù)據(jù)的示例
本篇文章主要介紹了vue+vuecli+webpack中使用mockjs模擬后端數(shù)據(jù)的示例,具有一定的參考價值,感興趣的小伙伴們可以參考一下。2017-10-10