Vue项目实现文件下载进度条功能
作者:A 风
大文件下载,花费的时间比较长,没有任何提示,用户体验很差,需要优化,提示文件在下载中,并且显示进度百分比,下面小编给大家带来了Vue项目实现文件下载进度条功能,感兴趣的朋友一起看看吧
Vue项目实现文件下载进度条
需求场景
大文件下载,花费的时间比较长,没有任何提示,用户体验很差。
需要优化,提示文件在下载中,并且显示进度百分比。
实现步骤
1.下载文件的方法,需要拿到当前进度。
2.每一次下载进度更新,需要监听变化,并且刷新页面显示的数据。
3.封装一个文件下载进度的组件。
下面一步步来实现:
1.获取文件下载进度
axios作为一个易用、简洁且高效的http库,有没有获取下载进度的方法呢?
打开axios官网查看一下,文档中有一个对原生进度事件的处理的方法
onDownloadProgress
允许为下载处理进度事件。
在项目中,我已经对axios进行了封装,并且增加了请求拦截器和响应拦截器。
在封装接口的文件interface.js中,新增一个下载文件,并且获取下载进度的方法。
export const downFileProgress =(url,parameter,callback,totalSize,uniSign) =>{ return axios({ url: url, params: parameter, method:'get' , responseType: 'blob', onDownloadProgress (progress) { callback(progress, totalSize, uniSign) } }) }
2.通过vuex状态管理下载进度
下载进度对象,需要通过vuex状态管理。在store文件下面的modules文件夹中,新建 downLoadProgress.js文件。
用来存放文件下载进度的数组 progressList 和修改进度列表方法,都在这里面。
const state = { // 文件下载进度 progressList: [], progressError: '', } 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 } } } const actions = { changeSetting({ commit }, data) { commit('CHANGE_SETTING', data) } } export default { namespaced: true, state, mutations, actions }
3.新增一个显示进度弹框的组件
<template> </template> <script> import { mapState } from 'vuex' export default { name: 'downLoadNotice', computed: { ...mapState({ 'progressList': state => state.downLoadProgress.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('downLoadProgress/DEL_PROGRESS', item.path) this.$notify.error({ title: '错误', message: '文件下载失败!' }); } } else { // 如果页面中没有该进度对象所对应的弹框,页面新建弹框,并在notify中加入该弹框对象,属性名为该进度对象的path(上文可知path是唯一的),属性值为$notify(element ui中的通知组件)弹框对象 this.notify[item.path] = this.$notify.success({ // title: 'info', dangerouslyUseHTMLString: true, customClass: 'progress-notify', message: `<p style="width: 100px;">正在下载<span class="${item.path}" style="float: right">${item.progress}%</span></p>`, // 显示下载百分比,类名为进度对象的path(便于后面更新进度百分比) showClose: false, duration: 0 }) } console.log(item.progress + '%', '-------------------------->') if (item.progress == 100) { // 如果下载进度到了100%,关闭该弹框,并删除notify中维护的弹框对象 this.notify[item.path].close() // delete this.notify[item.path] 上面的close()事件是异步的,这里直接删除会报错,利用setTimeout,将该操作加入异步队列 setTimeout(() => { delete this.notify[item.path] }, 1000) this.$store.commit('downLoadProgress/DEL_PROGRESS', item.path)// 删除caseInformation中state的progressList中的进度对象 } }) }, deep: true } } } </script> <style lang="scss" scoped> </style>
到此这篇关于Vue项目实现文件下载进度条功能的文章就介绍到这了,更多相关Vue文件下载进度条内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!