基于vue2.x实现loading bar(加载进度条)组件

在线演示地址Loading Bar

在这之前,我更新了有关一个单选框与复选框的组件实现,有兴趣的小伙伴也可以了解一下,今天我们来介绍一下loading bar 组件的实现原理。

加载进度条

实现思路

  • 整个组件ui部分有两部分组成,分别为顶部条形记载进度条,和spinner加载圈组成,整个部分包含在一个大的div里,并且通过fixed进行布局,然后我们通过定时器控制其增长,如果未结束,进度条会一直停留在最后的位置,等待end()事件的触发。如果end()事件触发,进度条加载结束,spinner停止旋转并且消失。
  • 因为可复用的关系,Loading Bar全局之后一个,我们通过this.$loading来操作实例。
  • 通过调用 $Loading 提供的三种方法来控制全局的加载进度条 start()end()error()

实现过程

  • ui部分以及样式
<template>
  <div class="w__loading-bar">
    <div
      class="w__loading-bar--bar"
      :class="isError ? 'w__loading-bar--error' : ''"
      role="bar"
      :style="{transform: 'translate3d(-'+(100-totalProgress)+'%, 0, 0)'}">
      <div class="w__loading-bar--peg">div>
    div>
    <div class="w__loading-bar--spinner" role="spinner" v-if="showSpinner">
      <div class="spinner-icon" :class="isError ? 'spinner-icon--error' : ''"
           :style="{'animation': 'w-spinner 400ms '+easing+' infinite'}">
      div>
    div>
  div>
template>

这里面注意的部分就是class中我们通过传递参数来控制样式,注意传递参数时拼接字符串的写法。其中tatalProgressd的初始值我们设置为0,我们之后会通过js来控制此值的大小,另一个参数时easing其控制变换的一种方式,默认值时linear具体样式文件loadingbar.css

  • data函数中的数据,组件通过全局进行注册,所以子组件不需要通过props接收参数
<script>
  export default{
    name: 'WLoadingBar',
    data () {
      return {
        speed: 5,
        easing: 'linear',//加载动画
        percentNum: 0,//每次前进的百分比
        totalProgress: 0,//控制顶部条形进度条x轴的位移
        showSpinner: true,//是否显示圆圈加载
        isError: false//是否发生错误
      }
    }
  }
script>
  • 下面时最关键的一个部分,我们通过Vue.extend(LoadingBar)来创建一个扩展实例的构造器LoadingBarConstructor,我们通过给构造器的原型上来添加一系列方法来实现组建的开始,结束、错误等功能。
let LoadingBarConstructor = Vue.extend(LoadingBar);
let timer = null, removeTimer = null;

let WLoadingBar = () => {
  return new LoadingBarConstructor()
};
LoadingBarConstructor.prototype.config = function (options) {
  Object.keys(options).forEach((key) => {
    if (key === 'isError' || key === 'totalProgress') {
      return;
    }
    this[key] = options[key]
  })
};

LoadingBarConstructor.prototype.init = function () {
  clearTimeout(timer);
  this.totalProgress = 0;
  this.isError = false;
  this.vm = this.$mount();
  document.body.appendChild(this.vm.$el);
  return this
};

LoadingBarConstructor.prototype.start = function () {
  this.init();
  timer = setInterval(() => {
    if (this.totalProgress < 90) {
      this.totalProgress += (this.percentNum || Math.random()) * this.speed;
    }
  }, 100);
};

LoadingBarConstructor.prototype.end = function () {
  timer || this.init();
  this.totalProgress = 100;
  clearTimeout(removeTimer);
  removeTimer = setTimeout(() => {
    clearTimeout(timer);
    timer = null;
    document.body.removeChild(this.vm.$el)
  }, 200)
};

我们来说下这些函数的功能,

  1. config该函数接收一个参数,参数是我们需要设置的配置,这里面使用了一个Object.keys()来遍历options配置里的可枚举属性,并且通过将其添加到实例对象上(过滤掉isErrortotalProgress)
  2. init函数进行初始化操作,清除定时器,并将实例进行挂载,通过dom操作将实例添加到body中。
  3. shart函数将进度条控制在90%以下,在此之下,通过定时器定时增加totalProgress的数值来实现进度条的变化。
  4. end函数我们将totalProgress设置为100完成加载,并且清除定时器,从body中移除dom
  5. error函数将进度条设置为报错样式。

注意:我们通过给构造器的原型上来添加一系列方法的时候千万不要试图使用箭头函数,不要问我为什么,就相当于我们vue中的methods一样,理由是箭头函数绑定了父级作用域的上下文,所以 this 将不会按照期望指向 Vue 实例,这一点希望大家在写代码的时候注意。


  • 父组件的调用

由于我的开发文档已经写的很详细了,大家详情可以参考我的开发文档来看组件的使用开发文档

LoadingBar config参数

参数 说明 类型 可选值 默认值
speed 加载速度 Number 0-100 5
easing spinner加载动画 String linear, ease, cubic-bezier… 贝萨尔曲线值
percentNum 每次前进的百分比 Float 0-1 Math.random()
showSpinner 是否显示spinner Boolean true, false 是否显示spinner

如果你在使用 WVUE-UI 时遇到问题,或者有好的建议,欢迎给我们提 Email 或 Github

你可能感兴趣的:(vue)