Vue3實(shí)現(xiàn)常見附件的預(yù)覽功能
前言
最近開發(fā)了一個(gè)建筑相關(guān)的移動(dòng)端項(xiàng)目,其中有各種附件預(yù)覽的功能。通過(guò)各種嘗試,總結(jié)出了一些常用的文件預(yù)覽方式。本文介紹vue3常用文件(pdf、word、excel、txt)的預(yù)覽。
一、pdf預(yù)覽
本文使用的pdf預(yù)覽是通過(guò) pdfjs-dist 插件,在 Vue3 使用的時(shí)候還是有一些坑。
首先通過(guò) npm 安裝插件
npm install --save pdfjs-dist
然后在頁(yè)面中引入
const PDF = require('pdfjs-dist')
啟動(dòng)項(xiàng)目之后就會(huì)報(bào)錯(cuò)如下:

仔細(xì)查看報(bào)錯(cuò)信息,是插件中使用了 es11 的語(yǔ)法 ?. 然而當(dāng)項(xiàng)目啟動(dòng),插件中的代碼沒有經(jīng)過(guò)編譯,導(dǎo)致項(xiàng)目不能啟動(dòng)。解決方案是在項(xiàng)目中配置webpack 針對(duì)于這個(gè)插件進(jìn)行編譯。
修改項(xiàng)目根目錄下 vue.config.js ,如果沒有就創(chuàng)建一個(gè),在文件中增加如下代碼:
// 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']
})
}
}
之后的錯(cuò)誤

需要在引入 pdfjs-dist 之后配置 workerSrc ,但是引入 pdfjs-dist/build/pdf.worker.entry 之后瀏覽器還是有個(gè)警告:Warning: Setting up fake worker. ,經(jīng)過(guò)各種原因查找,最終找到了一句描述:pdf.worker.js必須位于自己的文件中(而不是與pdf.js捆綁在一起)。否則它不能在服務(wù)工作線程中運(yùn)行。
解決方式:將 pdfjs-dist/build/pdf.worker.js 復(fù)制一份放到項(xiàng)目 public 目錄下。
pdf解析組件代碼
通過(guò) pdfjs-dist 加載pdf文件,獲取到總頁(yè)數(shù)將 canvas 遍歷到頁(yè)面上,然后編寫一個(gè)遞歸函數(shù)通過(guò) getPage 解析 pdf 的每一頁(yè)將pdf內(nèi)容渲染到 canvas 。以下示例就是封裝了一個(gè)解析pdf組件,通過(guò)傳遞文件鏈接全屏渲染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è)置移動(dòng)端,寬度設(shè)置鋪滿整個(gè)屏幕
const clientWidth = document.body.clientWidth
canvas.style.width = clientWidth + 'px'
// 根據(jù)pdf每頁(yè)的寬高比例設(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ù)覽就比較簡(jiǎn)單了,因?yàn)闆]有樣式,我們直接讀取文件的內(nèi)容,展示到頁(yè)面即可。
需要注意的是,如果需要正常顯示 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 ,會(huì)忽略復(fù)雜樣式,只是實(shí)現(xiàn)了簡(jiǎn)單內(nèi)容預(yù)覽,使用方式也很簡(jiǎn)單,通過(guò)http請(qǐng)求獲取文件的 ArrayBuffer ,再使用 mammoth.convertToHtml 將內(nèi)容轉(zhuǎn)換成 html。如果文件能夠外網(wǎng)訪問(wèn)并且機(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 插件,讀取文件的某個(gè) Sheet 中的內(nèi)容,然后把內(nèi)容轉(zhuǎn)換成 json 我們自己用json渲染表格。
npm install xsls --save
讀取出json內(nèi)容如下,默認(rèn)以第一行為 key。

也可以通過(guò) sheet_to_json 第二個(gè)參數(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實(shí)現(xiàn)常見附件的預(yù)覽功能的詳細(xì)內(nèi)容,更多關(guān)于Vue3預(yù)覽的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
keep-alive include和exclude無(wú)效問(wèn)題及解決
這篇文章主要介紹了keep-alive include和exclude無(wú)效問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-11-11
Vue3項(xiàng)目剛創(chuàng)建就報(bào)錯(cuò)的問(wèn)題及解決
這篇文章主要介紹了Vue3項(xiàng)目剛創(chuàng)建就報(bào)錯(cuò)的問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-10-10
vue配置啟動(dòng)項(xiàng)目自動(dòng)打開瀏覽器方式
這篇文章主要介紹了vue配置啟動(dòng)項(xiàng)目自動(dòng)打開瀏覽器方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-04-04
vue element 表頭添加斜線的實(shí)現(xiàn)代碼
這篇文章主要介紹了vue element 表頭添加斜線的實(shí)現(xiàn)代碼,代碼簡(jiǎn)單易懂,對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-11-11
Vue實(shí)現(xiàn)圖片輪播組件思路及實(shí)例解析
這篇文章主要介紹了Vue實(shí)現(xiàn)圖片輪播組件思路及實(shí)例解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-05-05
Vue實(shí)例創(chuàng)建和掛載的詳細(xì)過(guò)程
在 Vue.js 中,實(shí)例的掛載是一個(gè)非常重要的過(guò)程,它決定了 Vue 實(shí)例如何與 DOM 進(jìn)行交互,通過(guò)分析 Vue 源碼,特別是 Vue 的構(gòu)建函數(shù)和生命周期,我們可以了解掛載過(guò)程的詳細(xì)步驟,需要的朋友可以參考下2024-11-11
Vue實(shí)現(xiàn)下載文件而非瀏覽器直接打開的方法
對(duì)于瀏覽器來(lái)說(shuō),文本、圖片等可以直接打開的文件,不會(huì)進(jìn)行自動(dòng)下載,下面這篇文章主要給大家介紹了關(guān)于Vue實(shí)現(xiàn)下載文件而非瀏覽器直接打開的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-05-05

