在平時專案開發中,我們經常會對檔案做一些上傳操作,不僅僅要實作基本需求,也要兼顧用戶體驗,根據自己在作業中遇到的問題談談對圖片上傳的預覽以及上傳進度的優化,
1.搭建專案
基于Vue.js+axios搭建的專案,新建一個Index.Vue專案如下,基本結構可以先可以選擇檔案,預覽檔案,
<template>
<div >
<h2 >上傳圖片</h2>
選擇檔案:<input type="file" multiple="true" accept="image/gif, image/jpeg" @change="handleFileChange($event)">
<p>圖片預覽:</p>
<img v-show="imgPreViewSrc" :src="https://www.cnblogs.com/peerless1029/p/imgPreViewSrc" alt="圖片預覽">
<button v-show="file" @click="uploadFile">上傳檔案到服務器</button>
</div>
</template>
<script>
...
data(){
return{
imgPreViewSrc:'', //檔案預覽地址
file:null, //上傳檔案
}
}
methods:{
}
...
</script>
<style lang="less" scoped>
.text-center{
text-align: center;
}
.wrapper{
font-size: 16px;
width: 60%;
height: 100%;
margin: 0 20%;
border: 1px solid #ddd;
img{
width: 200px;
}
button{
width:120px;
height: 30px;
margin-top: 30px;
line-height: 30px;
border: 1px solid #CCC;
text-align: center;
}
}
</style>
input的型別type設定為file,可以選擇檔案,multipe屬性設定為true,一次可以選擇多個檔案,
運行專案,頁面如下:

2.選擇檔案以及預覽
選擇一個圖片檔案(bg.jpg),之前有在input系結檔案改變監聽方法,列印事件引數如下:

發現剛才選擇的檔案在Event>target>files下面
files是一個陣列,剛才只選擇了一張圖片,所以長度為1,圖片的名稱(name),大小(size),型別(type)都有包含,
2.1.設定檔案型別
在input標簽accept屬性設定檔案型別,當用戶打開檔案資源管理器選擇檔案時,會過濾掉其他型別檔案,能夠從源頭避免用戶選擇臟檔案,也更加方便用戶選擇檔案,
<input type="file" multiple="true" accept="image/gif, image/jpeg" @change="handleFileChange($event)">
2.2.圖片預覽
要將用戶選擇的檔案顯示到頁面上,以方便用戶下一步操作,因為用戶可能會從選擇的檔案中再挑選幾張圖片操作,例如上傳到服務器,
?圖片預覽要用到URL物件的URL.createObjectURL(file)方法生成一個blob地址,直接賦值給img標簽的src,頁面就可以展示,(URL.createObjectURL() 靜態方法會創建一個 DOMString,其中包含一個表示引數中給出的物件的URL,這個 URL 的生命周期和創建它的視窗中的 document 系結,這個新的URL 物件表示指定的 File 物件或 Blob 物件,)
在methods添加handleFileChange方法,預覽圖片
... // 檔案改變監聽事件 handleFileChange(evt){ console.log(evt); let file=evt.target.files[0]; this.file=file; let src=URL.createObjectURL(file); this.imgPreViewSrc=https://www.cnblogs.com/peerless1029/p/src; }, ...

3.顯示上傳檔案進度
選擇好檔案之后,檔案要上傳到服務器,有時候檔案很大或者網速很慢的情況下,用戶需要知道已經上傳進度,如果沒有上傳進度,用戶退出頁面那么檔案就上傳失敗了,
3.1.修改script檔案
- 引入axios,封裝上傳Promise函式
- 在methods里添加上傳方法uploadFile
<script> import axios from 'axios'; // 檔案上傳服務api const baseURL='http://127.0.0.1/api'; function upload (params,cb=null) { return new Promise((resolve, reject) => { axios.create({ baseURL, })({ url:'/upload/uploadFile/image', method:'post', data:params, // 上傳進度 onUploadProgress:function(progressEvent){ if(progressEvent.lengthComputable && cb){ cb(progressEvent); } }, }).then(res => { console.log(res.data); if(res.status===200){ resolve(res.data); }else{ reject(res.data); } }).catch(err => { reject(err); }); }); } ... // 上傳檔案到服務器 uploadFile(){ let file=this.file; if(file){ let formData = new FormData(); formData.append('file', file); upload(formData,(progressEvent)=>{ console.log(progressEvent); }); }else{ alert('請選擇檔案') } ... </script>
3.2.上傳進度
??在axios入參新增onUploadProgress方法,在檔案上傳程序中該方法會呼叫,引數包含上傳的一些資訊,
有關ProgressEvent的一些介紹:
- ProgressEvent 是一個用來測量底層操作進度的介面,可以測量HTTP請求(例如:一個 XMLHttpRequest請求、或者一個底層資源如img,audio,video等,ProgressEvent常用屬性值:
- ProgressEvent.lengthComputable:它是一個布林值標識,表明總共需要完成的作業量和已經完成的作業是否可以被底層所計算到,換而言之,它表示的就是程序是否是可以測量的,
- ProgressEvent.loaded:是一個unsigned long long型別,表示底層行程已經執行的作業量,所做的作業比率可以用屬性和ProgressEvent.total計算,當使用HTTP下載資源時,這只表示內容本身的一部分,而不是頭和其他開銷,
- ProgressEvent.total:是unsigned long long型別,表示底層行程正在執行的作業總量,當使用HTTP下載資源時,這只表示內容本身,而不是頭和其他開銷,
點擊上傳按鈕,打開控制臺:

可以發現ProgressEvent中loaded屬性值為圖片檔案上傳的大小,total為檔案的大小,
3.3.在頁面添加進度條
為了組件通用化,新建一個Progress.vue組件,接受一個progressValue進度引數,
<template>
<div >
<div >
<p v-if="progressValue<100">上傳進度:{{progressValue}}%</p>
<p v-else>上傳成功!</p>
<progress :value="https://www.cnblogs.com/peerless1029/p/progressValue" max="100"></progress>
</div>
</div>
</template>
<script>
export default {
props:['progressValue'],
name: 'Progress',
};
</script>
<style lang="less" scoped>
.progress-box{
position: fixed;
top:0;
left:0;
bottom: 0;
right:0;
background: rgba(0,0,0,0.5);
.progress-content{
position: absolute;
top:50%;
left:50%;
width: 300px;
height: 76px;
padding: 8px 30px;
transform: translate(-150px,-38px);
background: #fff;
border-radius: 8px;
p{
margin-bottom: 5px;
}
progress{
width: 100%;
height: 22px;
}
progress::-webkit-progress-bar{
background-color:#d7d7d7;
}
progress::-webkit-progress-value{
background-color:orange;
}
}
}
</style>
在div末尾添加Progress組件,再修改Index.vue檔案methods的上傳方法:
<template> <div > ... <Progress :progressValue="https://www.cnblogs.com/peerless1029/p/progressValue" v-if="isShowProgressBox"></Progress> </div> </template> <script> import Progress from '../components/Progress'; ... // 上傳檔案到服務器 uploadFile(){ let file=this.file; if(file){ let formData = new FormData(); formData.append('file', file); upload(formData,(progressEvent)=>{ this.isShowProgressBox=true; this.progressValue=https://www.cnblogs.com/peerless1029/p/parseFloat((progressEvent.loaded/progressEvent.total*100).toFixed(2)); if(this.progressValue=https://www.cnblogs.com/peerless1029/p/==100){ let timer=setTimeout(()=>{ this.isShowProgressBox=false; clearTimeout(timer); timer=null; },500); } }); }else{ alert('請選擇檔案'); } ... </script>
然后再上傳圖片,如下:

可以看到,點擊上傳后,頁面出現進度模態框,讓用戶知道已經上傳百分比,優化用戶體驗,
關于圖片上傳其實還能優化的方面還有很多,后續在作業中遇到問題再加以論述,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/179042.html
標籤:JavaScript
