多个文件加载显示总体进度条js

28 篇文章 0 订阅

前言

需求是,进入页面加载多个vtk3d模型文件,因为文件特别大,从服务器下载就比较慢,需要做个进度条优化用户体验。
如下图所示:

在这里插入图片描述

思路

1、事件总线传递值 (文件总大小、当前文件加载大小)
		由于接口调用封装的太深,与组件难以关联,要么进行vuex保存,要么事件总线(事件监听,事件发布),
		当前采用的是事件总线的方式处理(便于理解,后期可以用vuex优化性能)
2、this.$set()动态保存每一个文件进度
		多个文件都要分别保存文件总大小、当前文件加载大小,这里采用this.$set()进行数据存储操作
3、对象、数组求和,求出总的文件大小和总的加载大小
4、样式动态化

步骤

  1. 事件总线

    //event-bus.js
    import Vue from 'vue'
    export const EventBus = new Vue()
    
    	import { 
    	  EventBus 
    	} from "../../../../../../src/components/core/event-bus.js";
    	
    	// 接口逻辑
    	xhr.onprogress =  (event)=>{
    	   EventBus.$emit(`${url}`,{load:event.loaded,total:event.total})
    	  };
    		
    	解释:因为每个文件的url都是唯一的,所以漫游的事件名称就按url作为事件名称,传递的是一个对象
    	接口逻辑每50ms执行一次,此处不需要做其他事项
    

    完整的接口逻辑 (原生接口请求,对接口熟悉的可以跳过下述)

    function openAsyncXHR(method, url, options = {}) {
      const xhr = new XMLHttpRequest();
      xhr.onprogress =  (event)=>{
      	EventBus.$emit(`${url}`,{load:event.loaded,total:event.total})
      };
      xhr.open(method, url, true);
      xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); 
      if (options.headers) { // 这个位置是传递token值的
        Object.entries(options.headers).forEach(([key, value]) =>
          xhr.setRequestHeader(key, value)
        );
      }
      console.log('接口位置1', xhr) // 这个位置已经执行完了xhr
      if (options.progressCallback) {
        console.log('options.progressCallback',options.progressCallback) // 没有走这个
        xhr.addEventListener('progress', options.progressCallback);
      }
      return xhr;
    }
    function fetchBinary(url, options = {}) {
      return new Promise((resolve, reject) => {
        const xhr = openAsyncXHR('POST', url, options);
        xhr.onreadystatechange = (e) => {
          if (xhr.readyState === 4) {
            if (xhr.status === 200 || xhr.status === 0) {
              resolve(xhr.response);
            } else {
              reject({ xhr, e });
            }
          }
        };
        // Make request
        xhr.responseType = 'arraybuffer';
        xhr.send();
      });
    }
    
  2. 组件使用

// 定义属性:data
    progress:{}, // 接收漫游的数据
	percentage:'', // 百分比
     load:0,// 文件总加载大小
     sum:0, // 文件总大小
     time:'', // 记录时间
     loadeveTime:'' //平均速度
 mounted钩子函数下
	this.fileLists.forEach((item)=>{ 
	//文件遍历 根据每个url定义监听
     EventBus.$on(`${item.url}`,(msg)=>{ 
     	if(!this.time){ // 记录当前时间、求平均速度
         this.time = new Date().getTime();
       }
     		//1、 事件总线获取当前的下载速度
       console.log('msg',msg) 
       		// msg是获取的是对象(每个文件的总大小 ,当前加载的大小)
       this.$set(this.progress,`${item.url}`,msg)
       		// 在this.progress动态添加以url作为属性名的对象
       
       		//2、对this.progress下的数据进行求和,取出总的文件大小 、总的加载数据大小		
       this.load = Object.values(this.progress).reduce(function (pre,cur) {
       		// 对象嵌套对象,对内层对象中相同属性的求和
           return pre+cur.load;
       },0)
       this.loadeveTime = this.load*1000/(new Date().getTime()-this.time);// 平均速度
       this.sum = Object.values(this.progress).reduce(function (pre,cur) {
           return pre+cur.total;
       },0)
       this.percentage = ((this.load/this.sum)*99).toFixed(2)
       
       	// 3、页面数据渲染
       document.getElementById('son').style.width=this.percentage+'%'
     })
   })

解释:
对Object.values(this.progress).reduce(function (pre,cur) {}求和的理解
我的这篇文章有详细介绍:对象中嵌套对象,求内层对象某个相同属性和 js

 页面
<div :class="$style.progress">
      {{percentage}}%
      <div :class="$style.father">
        <div id="son" :class="$style.son"></div>
      </div>
      {{loadeveTime }}M/s
    </div>
.progress{
  margin: 0 auto;
  margin-top: 25%;
  font-size: 16px;
  font-family: PingFang SC;
  font-weight: bold;
  color: #F5F5F5;
}
.father{
  width: 364px;
  height: 15px;
  margin: 0 auto;
  position: relative;
  background: linear-gradient(0deg, rgba(0, 0, 0, 0.17), rgba(255, 255, 255, 0.17));
}
.son{
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  /* width: 201px; */
  background: #1E66B7;
}

3.其他
如果存在total为0的情况

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值