Vue文件下載進度條的實現(xiàn)過程
需求場景:
1、大文件壓縮過后依舊很大,接口返回response速度過慢,頁面沒有任何顯示,體驗太差。
2、需要在瀏覽器顯示正在加載中的狀態(tài)優(yōu)化顯示,提高用戶體驗
實現(xiàn)原理:
1、使用onDownloadProgress方法API獲取進度及文件大小等數(shù)據
2、mixin混入實現(xiàn)監(jiān)聽進度條進度
3、vuex修改進度條進度
優(yōu)化過程:
使用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()} ` // 可能會連續(xù)點擊下載多個文件,這里用時間戳來區(qū)分每一次下載的文件
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表示已經下載的數(shù)量,total表示總數(shù)量,這里計算出百分比
let downProgress = Math.floor((progress.loaded / total) * 100)
// 將此次下載的文件名和下載進度組成對象再用vuex狀態(tài)管理
this.$store.commit('SET_PROGRESS', { path: uniSign, progress: downProgress })
}創(chuàng)建component同等級mixin文件夾,文件夾創(chuàng)建index.js
import { mapState } from 'vuex'
export const mixins = {
computed: {
...mapState({
progressList: state => state.progressList
})
},
data () {
return {
notify: {} // 用來維護下載文件進度彈框對象
}
},
watch: {
// 監(jiān)聽進度列表
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 stateconst 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 {
// 當前進度列表為空,沒有下載任務,直接將該進度對象添加到進度數(shù)組內
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)
}最終效果圖

參考文章:
到此這篇關于Vue文件下載進度條的實現(xiàn)過程的文章就介紹到這了,更多相關Vue下載進度條內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
vue改變數(shù)據后數(shù)據變化頁面不刷新的解決方法
這篇文章主要給大家介紹了關于vue改變數(shù)據后數(shù)據變化頁面不刷新的解決方法,vue比較常見的坑就是數(shù)據(后臺返回)更新了,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下2023-07-07

