vue+elementUI實(shí)現(xiàn)多文件上傳與預(yù)覽功能實(shí)戰(zhàn)記錄(word/PDF/圖片/docx/doc/xlxs/txt)
需求
最近在做vue2.0+element UI的項(xiàng)目中遇到了一個(gè)需求:需求是多個(gè)文件上傳的同時(shí)實(shí)現(xiàn)文件的在線預(yù)覽功能。需求圖如下:
看到這個(gè)需求的時(shí)候,小栗腦袋一炸。并不知道該如何下手,之前的實(shí)踐項(xiàng)目中也并沒(méi)有遇到相似的功能。因此也廢了一番功夫想要實(shí)現(xiàn)這樣一個(gè)功能。
首先先查看elemnt UI的官方文檔發(fā)現(xiàn),大部分的實(shí)現(xiàn)文件上傳效果的功能,即使可以提供預(yù)覽的功能,但是不能指定該功能的樣式和內(nèi)容有一定的局限性
然后小栗查找“多文件上傳預(yù)覽、PDF預(yù)覽、word預(yù)覽等關(guān)鍵詞”,發(fā)現(xiàn)大部分的大佬的方法都是實(shí)現(xiàn)了圖片預(yù)覽,并沒(méi)有實(shí)現(xiàn)多文件上傳(也可能是因?yàn)槲也](méi)有找到相關(guān)的功能)。
因此小栗決定自己封裝這個(gè)功能,并希望有朋友能在這個(gè)的基礎(chǔ)上進(jìn)行調(diào)整優(yōu)化。期待你們的參與哦~~
話不多說(shuō),上才藝
實(shí)現(xiàn)需求
1、利用on-preview+window.open()實(shí)現(xiàn)簡(jiǎn)易版預(yù)覽效果
查看element UI文檔后發(fā)現(xiàn)el-upload里面有一個(gè)Attribute叫on-preview( 點(diǎn)擊文件列表中已上傳的文件時(shí)的鉤子)是專門(mén)用來(lái)做文件預(yù)覽的。點(diǎn)擊文件就可以出發(fā)該函數(shù)。再結(jié)合window.open()方法可以直接完成一個(gè)新開(kāi)窗口頁(yè)的查看文件
代碼如下:
HTML部分
//on-preview="Previewf"是必須的也是預(yù)覽的關(guān)鍵 <el-upload class="upload-demo" :action="uploadUrl" :on-success="handlePreview" :on-remove="handleRemove" :before-upload="beforeUpload" :on-preview="Previewf" multiple :limit="5" :on-exceed="handleExceed" :file-list="file-list" :accept="accepts" > <el-button icon="el-icon-upload2" @click="uploadFileClick($event)" >上傳文件</el-button > </el-upload>
methods部分
Previewf(file) { console.log(file); // window.open(file.response) if (file) { const addTypeArray = file.name.split("."); const addType = addTypeArray[addTypeArray.length - 1]; console.log(addType); if (addType === "pdf") { let routeData = this.$router.resolve({ path: "/insurancePdf", query: { url: file.response, showBack: false }, }); window.open(routeData.href, "_blank"); } //".rar, .zip, .doc, .docx, .xls, .txt, .pdf, .jpg, .png, .jpeg," else if (addType === "doc" || addType === "docx" || addType === "xls") { window.open( "http://view.officeapps.live.com/op/view.aspx?src=" + file.response ); } else if (addType === "txt") { window.open(file.response); } else if (["png", "jpg", "jpeg"].includes(addType)) { window.open(file.response); } else if (addType === "rar" || addType === "zip") { this.$message({ message: "該文件類型暫不支持預(yù)覽", type: "warning", }); return false; } } },
功能預(yù)覽
點(diǎn)擊藍(lán)色的文件部分就可以出現(xiàn)新開(kāi)頁(yè)面,這個(gè)簡(jiǎn)易的利用element UI就完成了這個(gè)功能啦~有沒(méi)有覺(jué)得還是不那么難呢?
2、封裝組件實(shí)現(xiàn)更完整的上傳完成、預(yù)覽功能
上述的功能可以完成預(yù)覽,但與我們的需求有一部分的出入,不能夠完全滿足我的業(yè)務(wù)需求,因此在element UI的基礎(chǔ)上,我進(jìn)行了組件封裝,以求完成以下功能:
話不多說(shuō),還是上代碼:
HTML部分
/* 重點(diǎn)關(guān)注的代碼: :show-file-list="false" ref="contentWrap */ <el-upload class="upload-demo" ref="uploadCom" :show-file-list="false" :action="uploadUrl" :on-success="onSuccess" :on-remove="handleRemove" :before-upload="beforeUpload" multiple :limit="5" :on-exceed="handleExceed" :file-list="file-list" :accept="accepts" > <el-button icon="el-icon-upload2" @click="uploadFileClick($event)" >將文件拖到此處,或<em>點(diǎn)擊上傳</em></el-button > <div slot="tip" class="el-upload__tip"> 支持?jǐn)U展名:.rar .zip .doc .docx .xls .txt .pdf .jpg .png .jpeg,最多上傳5個(gè)文件,每個(gè)大小不超過(guò)50Mb </div> </el-upload> <div class="flex mt20" v-if="file-list.length > 0"> <div class="items-wrap" ref="contentWrap" :style="wrapHeight <= 70 ? 'height: auto' : `height: 60px;`" :class="{ noHidden: noHidden }" > <uploadfile-item v-for="(item, index) in file-list" :key="index" :file="item" @cancel="cancelFile" :showDel="true" class="mr20" ></uploadfile-item> </div> <div class="on-off" v-if="wrapHeight > 70" @click="noHidden = !noHidden" > {{ noHidden ? "收起" : "更多" }} </div> </div>
methods部分
import UploadfileItem from ""; export default { components: { UploadfileItem, }, data() { return { noHidden: true, wrapHeight: 0, delDialogitem: 0, imgLoad: false, centerDialogVisible: false, file-list:[], }, }; }, methods: { cancelFile(file) { console.log(file); }, // 上傳文件只能添加五條 uploadFileClick(event) { if (this.formLabelAlign.annex.length === 5) { this.$message({ type: "warning", message: "最多只可以添加五條", }); event.stopPropagation(); return false; } }, // onSuccess(response, file, annex) { if (!response) { this.$message.error("文件上傳失敗"); } else { this.imgLoad = false; this.$message({ message: "上傳成功!", type: "success", }); } }, beforeUpload(file) { console.log(file); }, handleExceed(files, ) { console.log(file); }, };
UploadfileItem組件內(nèi)容
<template> <div class="file-style-box"> <div class='upload-file-item'> <img :src="imgsrc[getEnd(file.fileName)]" alt=""> <div> <p class='file-name'> <span class='name'>{{file.fileName}}</span> </p> <div class='option'> <span class='size'>{{file.size | toKB}}kb</span> <div> <span v-if='showDel && (isPdf(file) || isImg(file))' @click='previewHandler(file.url)' class='preview mr10'>預(yù)覽</span> <a v-if='!showDel' @click='downLoadHandler' class='preview' :href="file.url" rel="external nofollow" >下載</a> <span v-if='showDel' class='mr10 success'>上傳完成</span> </div> </div> <div class='delBtn' v-if='showDel' @click='cancelHanlder(file)'> <img src="@/assets/public/tips-err.png" alt=""> </div> </div> </div> <el-dialog title="圖片預(yù)覽" width="800px" class="imgDlgBox" :visible.sync="imgDlgVisible" :close-on-click-modal="true" :modal="false" append-to-body > <img :src="imgUrl" alt=""> </el-dialog> </div> </template> <script> export default { props: { file: { type: Object, default: {} }, showDel: { type: Boolean, default: false } }, data() { return { imgDlgVisible: false, imgUrl: '', pdfUrl: '', imgsrc: { /* *imgsrc 是關(guān)于內(nèi)部靜態(tài)圖片的顯示的路徑,需要自己設(shè)置 *示例"xls": require('@/assets/image/xls.png'), xis的文件所需要加載的路徑是;assets文件下的image文件夾下的xls.png */ "rar": require('@'), "zip": require('@'), "pdf": require('@'), "jpg": require('@'), "jpeg": require('@'), "png": require('@'), "doc": require('@'), "docx": require('@'), "txt": require('@'), "xls": require('@/assets/image/xls.png'), } } }, filters: { toKB(val) { return (Number(val) / 1024).toFixed(0); } }, methods: { cancelHanlder(item) { this.$emit('cancel', item) }, previewHandler(data) { if (data) { const addTypeArray = data.split("."); const addType = addTypeArray[addTypeArray.length - 1]; if (addType === "pdf") { let routeData = this.$router.resolve({ path: "/insurancePdf", query: { url: data, showBack: false } }); window.open(routeData.href, '_blank'); } else if (addType === "doc") { window.open( `https://view.officeapps.live.com/op/view.aspx?src=${data}` ); } else if (addType === "txt") { window.open(`${data}`); } else if (['png','jpg','jpeg'].includes(addType)) { // 圖片類型 this.imgDlgVisible = true this.imgUrl = data } } }, } </script> <style lang='scss'> .file-style-box { padding: 10px 10px 0 0; } .imgDlgBox { .el-dialog { .el-dialog__body { text-align: center; img { width: 700px; height: auto; } } } } .upload-file-item { background: #FAFAFA; border-radius: 4px; padding: 5px 10px; margin-bottom: 10px; display: flex; font-size: 14px; width: 236px; box-sizing: border-box; position: relative; img { width: 32px; height: 40px; margin-top: 5px; margin-right: 10px; } .option { display: flex; align-items: center; justify-content: space-between; } .file-name { width: 163px; display: flex; flex-wrap: nowrap; font-size: 14px; color: #333; font-weight: 400; .name { white-space: nowrap; text-overflow: ellipsis; overflow: hidden; } .end { flex: 0 0 auto; } .el-button{ border: none; padding: 0px; width: 90%; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } } .size { color: #969696; } .success { color: #78C06E; } .delBtn { position: absolute; top: -14px; right: -18px; cursor: pointer; img { width:16px; height:16px } } // .del { // color: #E1251B; // cursor: pointer; // } .preview { color: #0286DF; cursor: pointer; } .mr10 { margin-right: 10px; } } </style>
效果圖
以上就可以實(shí)現(xiàn)實(shí)現(xiàn)多文件上傳+預(yù)覽(word/PDF/圖片/docx/doc/xlxs/txt)啦,希望這樣的實(shí)現(xiàn)方式也對(duì)你有幫助哦
追加關(guān)于問(wèn)的比較多的問(wèn)題回復(fù)
1、imgsrc路徑
imgsrc: { "rar": require('@/assets/material/zip.png'), } 這個(gè)位置會(huì)報(bào)錯(cuò)
這里報(bào)錯(cuò)是因?yàn)榇颂幍膬?nèi)容是靜態(tài)資源,他是我們預(yù)覽圖片的一些細(xì)節(jié),長(zhǎng)成如下圖所示:
你本地應(yīng)該也需要配置這樣一個(gè)文件夾的路徑就可以啦。
2、顯示原本elementui的那個(gè)上傳樣式
重點(diǎn)關(guān)注el- upload的代碼 :show-file-list="false" //關(guān)閉原來(lái)的上傳樣式 ref="contentWrap //這個(gè)是通過(guò)父子組件傳值將子組件的頁(yè)面
3、file.response顯示沒(méi)有這個(gè)屬性和方法
file.response是element UI的內(nèi)置的組件的方法,引入element UI使用文件上傳組件就可以實(shí)現(xiàn)
我之前寫(xiě)這兒的file.response 時(shí)候,有一個(gè)傳遞值也有問(wèn)題,好像是element UI的鉤子函數(shù)的問(wèn)題,你先打印file。然后看是不是file.response ,不是的話 查看一下file的其他屬性,有一個(gè)是跟回調(diào)相關(guān)的返回值
就可以解決啦
4、https://view.officeapps.live.com/op/view.aspx?src=${data}是干嘛的?預(yù)覽PDF需要安裝其他的插件嗎?
首先:不需要再安裝其他預(yù)覽資源加載包,所有的預(yù)覽都是通過(guò)windom.open()方法打開(kāi)一個(gè)新窗口預(yù)覽。
PDF的預(yù)覽時(shí)使用的office官方的接口文檔:`https://view.officeapps.live.com/op/view.aspx?src=${data}就可以預(yù)覽PDF文檔了。
圖片的預(yù)覽是通過(guò)dialog的彈窗實(shí)現(xiàn)的,就簡(jiǎn)單一個(gè)彈窗
rar和zip不支持預(yù)覽,只能下載查看
總結(jié)
到此這篇關(guān)于vue+elementUI實(shí)現(xiàn)多文件上傳與預(yù)覽功能(word/PDF/圖片/docx/doc/xlxs/txt)的文章就介紹到這了,更多相關(guān)vue+elementUI多文件上傳預(yù)覽內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue單頁(yè)開(kāi)發(fā)父子組件傳值思路詳解
這篇文章主要介紹了vue單頁(yè)開(kāi)發(fā)父子組件傳值思路詳解,本文是小編抽空整理的思路,感興趣的朋友跟隨腳本之家小編一起學(xué)習(xí)吧2018-05-05Vue中在data里面調(diào)用method方法的實(shí)現(xiàn)
這篇文章主要介紹了Vue中在data里面調(diào)用method方法的實(shí)現(xiàn),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-06-06vue3?中使用?jsx?開(kāi)發(fā)的詳細(xì)過(guò)程
這篇文章主要介紹了vue3?中使用?jsx?開(kāi)發(fā),本文著重說(shuō)一下在使用 .vue 文件和 .jsx 文件在使用語(yǔ)法上的差異,需要的朋友可以參考下2022-09-09vue2.x版本中computed和watch的使用及關(guān)聯(lián)和區(qū)別
這篇文章主要介紹了vue2.x版本中computed和watch的使用及關(guān)聯(lián)和區(qū)別,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,需要的小伙伴可以參考一下2022-07-07vue select選擇框數(shù)據(jù)變化監(jiān)聽(tīng)方法
今天小編就為大家分享一篇vue select選擇框數(shù)據(jù)變化監(jiān)聽(tīng)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-08-08Vue數(shù)據(jù)驅(qū)動(dòng)表單渲染,輕松搞定form表單
這篇文章主要介紹了Vue數(shù)據(jù)驅(qū)動(dòng)表單渲染,輕松搞定form表單,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-07-07vue3+electron12+dll開(kāi)發(fā)客戶端配置詳解
本文將結(jié)合實(shí)例代碼,介紹vue3+electron12+dll客戶端配置,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-06-06