Vue文件下載進度條的實現過程
需求場景:
1、大文件壓縮過後依舊很大,接口返回response速度過慢,頁面沒有任何顯示,體驗太差。
2、需要在瀏覽器顯示正在加載中的狀態優化顯示,提高用戶體驗
實現原理:
1、使用onDownloadProgress方法API獲取進度及文件大小等數據
2、mixin混入實現監聽進度條進度
3、vuex修改進度條進度
優化過程:
使用onDownloadProgress封裝一個下載文件的方法
downFileProgress: function (url, params, headers, blenderApiUrl, callback, uniSign) { return axios({ url: url, params: params, method: 'get', responseType: 'blob', baseURL: blenderApiUrl, headers: headers, onDownloadProgress (progress) { callback(progress, uniSign) } }) }
在下載文件的地方,使用封裝的方法downFileProgress
downOrgFile (row) { let uniSign = `${new Date().getTime()} ` // 可能會連續點擊下載多個文件,這裡用時間戳來區分每一次下載的文件 const url = `${this.$api.LifeInsuranceScenario2DownFile}/${row.account_name}/${row.task_id}` const baseUrl = this.iframeData.blenderApiUrl this.$http.downFileProgress(url, {}, this.headers, baseUrl, this.callBackProgress, uniSign).then(res => { if (!res) { this.$sweetAlert.errorWithTimer('文件下載失敗!') return } if (typeof window.navigator.msSaveBlob !== 'undefined') { window.navigator.msSaveBlob(new Blob([res.data]), '中間項下載.zip') } else { let url = window.URL.createObjectURL(new Blob([res.data])) let link = document.createElement('a') link.style.display = 'none' link.href = url link.setAttribute('download', 'xxx.zip') document.body.appendChild(link) link.click() link.remove() } }) }, callBackProgress (progress, uniSign) { let total = progress.srcElement.getResponseHeader('Real-Content-Length') // progress對象中的loaded表示已經下載的數量,total表示總數量,這裡計算出百分比 let downProgress = Math.floor((progress.loaded / total) * 100) // 將此次下載的文件名和下載進度組成對象再用vuex狀態管理 this.$store.commit('SET_PROGRESS', { path: uniSign, progress: downProgress }) }
創建component同等級mixin文件夾,文件夾創建index.js
import { mapState } from 'vuex' export const mixins = { computed: { ...mapState({ progressList: state => state.progressList }) }, data () { return { notify: {} // 用來維護下載文件進度彈框對象 } }, watch: { // 監聽進度列表 progressList: { handler (n) { let data = JSON.parse(JSON.stringify(n)) data.forEach(item => { const domList = [...document.getElementsByClassName(item.path)] if (domList.find(i => i.className === item.path)) { // 如果頁面已經有該進度對象的彈框,則更新它的進度progress if (item.progress) domList.find(i => i.className === item.path).innerHTML = item.progress + '%' if (item.progress === null) { // 此處容錯處理,如果後端傳輸文件流報錯,刪除當前進度對象 this.$store.commit('DEL_PROGRESS', item.path) this.$notify.error({ title: '錯誤', message: '文件下載失敗!' }) } } else { // 如果頁面中沒有該進度對象所對應的彈框,頁面新建彈框,並在notify中加入該彈框對象,屬性名為該進度對象的path(上文可知path是唯一的),屬性值為$notify(element ui中的通知組件)彈框對象 this.notify[item.path] = this.$notify.success({ dangerouslyUseHTMLString: true, customClass: 'progress-notify', message: `<p style="width: 150px;line-height: 13px;">中間項正在下載<span class="${item.path}" style="float: right">${item.progress}%</span></p>`, // 顯示下載百分比,類名為進度對象的path(便於後面更新進度百分比) showClose: true, duration: 0 }) } if (item.progress === 100) { // 如果下載進度到瞭100%,關閉該彈框,並刪除notify中維護的彈框對象 // this.notify[item.path].close() // 上面的close()事件是異步的,直接delete this.notify[item.path]會報錯,利用setTimeout,將該操作加入異步隊列 setTimeout(() => { delete this.notify[item.path] }, 1000) this.$store.commit('DEL_PROGRESS', item.path) // 刪除caseInformation中state的progressList中的進度對象 } }) }, deep: true } } }
下載方法的組件引入mixin
import { mixins } from '../mixin/index' export default { mixins: [mixins], ...... }
Vuex配置進度條
const state = { progressList: [] } export default state
const mutations = { SET_PROGRESS: (state, progressObj) => { // 修改進度列表 if (state.progressList.length) { // 如果進度列表存在 if (state.progressList.find(item => item.path === progressObj.path)) { // 前面說的path時間戳是唯一存在的,所以如果在進度列表中找到當前的進度對象 state.progressList.find(item => item.path === progressObj.path).progress = progressObj.progress // 改變當前進度對象的progress } } else { // 當前進度列表為空,沒有下載任務,直接將該進度對象添加到進度數組內 state.progressList.push(progressObj) } }, DEL_PROGRESS: (state, props) => { state.progressList.splice(state.progressList.findIndex(item => item.path === props), 1) // 刪除進度列表中的進度對象 }, CHANGE_SETTING: (state, { key, value }) => { // eslint-disable-next-line no-prototype-builtins if (state.hasOwnProperty(key)) { state[key] = value } } } export default mutations
export const getProgressList = state => state.progressList
export const changeSetting = function ({ commit }, data) { commit('CHANGE_SETTING', data) } export const setprogress = function ({ commit }, data) { commit('SET_PROGRESS', data) } export const delprogress = function ({ commit }, data) { commit('DEL_PROGRESS', data) }
最終效果圖
參考文章:
juejin.cn/post/702437…
到此這篇關於Vue文件下載進度條的實現過程的文章就介紹到這瞭,更多相關Vue下載進度條內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- vue項目實現文件下載進度條功能
- vue中使用mixins/extends傳入參數的方式
- vue3 mixin 混入使用方法
- uni-app小程序沉浸式導航實現的全過程
- vue cli 局部混入mixin和全局混入mixin的過程