ChenJiaH / blog

📝个人博客 - 欢迎关注 👀 和点赞 ⭐️
https://chenjiahao.xyz/blog
MIT License
9 stars 7 forks source link

基于Vue实现加载进度条插件 #25

Open ChenJiaH opened 5 years ago

ChenJiaH commented 5 years ago

首发于微信公众号《前端成长记》,写于 2018.02.26

概述

随着越来越多的网站采用顶部加载进度条来表示加载进度及状态,效果如下:

image

查看在线示例

使用

配置文档

可以单独在请求中使用,也可以使用在路由切换过程中。比如结合 vue-router 使用:

import loadingBar from  '../src/components/loading-bar/loading-bar'
router.beforeEach((to, from, next) => {
   if(to.path === "/" && to.name === "Home") {
      router.replace({path: '/summary'});
      next();
   } else {
      loadingBar.start();
      next();
   }
});
router.afterEach((to, from) => {
   loadingBar.finish();
});

源码

Github

实现方式

基于 Vue 的调用方式一般有两种: 组件方式 插件方式

推荐使用 插件方式 调用,当然如果只有一处使用的话,也可以使用组件方式。

  1. 首先编写一个单文件组件

该文件中含有进度条的样式结构以及一些动态入参,示例:

<template>
    <transition name="loading-fade">
        <div class="jrv-loading-bar" :style="barStyle" v-show="show">
            <div class="jrv-loading-bar-inner" :style="{'width': innerWidth, 'background-color': [status == 'success' && successBg, status == 'fail' && failBg,],}"
                 :class="{'jrv-loading-bar-inner_success': status == 'success', 'jrv-loading-bar-inner_fail': status == 'fail'}"></div>
        </div>
    </transition>
</template>
<script>
   export default {
      name: "jrvLoadingBar",
      data() {
         return {
            percent: 0,
            status: 'success',
            show: false,
            barBg: 'transparent',
            successBg: null,
            failBg: null,
         }
      },
      computed: {
         barStyle() {
            return {
               backgroundColor: `${this.barBg}`,
            }
         },
         innerWidth() {
            return this.percent + '%';
         },
      },
   }
</script>
<style type="text/scss" lang="scss">
    @import '../../../styles/components/_loading-bar.scss';
</style>

在上述代码中,可以发现入参主要有: percent(进度) status(状态) show(显示与否) barBg(背景色) successBg(成功背景色) failBg(失败背景色),所以使用起来,只需要修改这几个主要动态参数即可。

  1. 接下来是插件方式的调用

创建一个 loading-bar.js 文件,代码如下:

/**
 * @Author: Created By McChen
 * @Date: 2017/10/27
 * @Mail: mcchen.club@gmail.com
 * @Version: V1.0.0
 */

import Vue from 'vue'

// 引入上面定义的单文件组件
import loadingBar from './src/loading-bar'

// 实例对象
let instance;
// 定时器
let timer;

let LoadingBar = {
   create () {
      if(!instance) {
         // 组件构造器
         const LoadingBarConstructor = Vue.extend(loadingBar);
         instance = new LoadingBarConstructor({});
         // 挂载实例
         instance.$mount();
         document.body.appendChild(instance.$el);
      }
   },
   update (options) {
      // 修改动态入参值
      for(let key in options) {
         instance[key] = options[key];
      }
   },
   hide () {
      let timer1 = setTimeout(() => {
         this.update({
            show: false
         });
         clearTimeout(timer1);

         let timer2 = setTimeout(() => {
            this.update({
               percent: 0
            });
            clearTimeout(timer2)
         }, 200);
      }, 800);
   },
   destroy () {
      document.body.removeChild(document.getElementsByClassName('jrv-loading-bar')[0]);
   },
   clearTimer () {
      if(timer) {
         clearInterval(timer);
         timer = null;
      }
   }
};
// 默认先创建一个
LoadingBar.create();

export default {
   config (obj) {
      LoadingBar.update({
         barBg: obj.barBg,
         successBg: obj.successBg,
         failBg: obj.failBg,
      })
   },
   start () {
      LoadingBar.create();

      if(timer) {
         return false;
      } else {
         let percent = 0;

         LoadingBar.update({
            percent: percent,
            status: 'success',
            show: true
         });

         timer = setInterval(() => {
            percent += Math.floor(Math.random () * 3 + 5);
            if (percent > 90) {
               clearInterval(timer);
               timer = null;
            }
            LoadingBar.update({
               percent: percent,
               status: 'success',
               show: true
            });
         }, 200);
      }
   },
   update (percent) {
      LoadingBar.clearTimer();
      LoadingBar.update({
         percent: percent,
         status: 'success',
         show: true
      });
   },
   finish () {
      if(timer) {
         LoadingBar.clearTimer();
         LoadingBar.update({
            percent: 100,
            status: 'success',
         });
         LoadingBar.hide();
      } else {
         LoadingBar.hide();
      }
   },
   error () {
      LoadingBar.clearTimer();
      LoadingBar.update({
         percent: 100,
         status: 'fail',
      });
      LoadingBar.hide();
   },
   destroy () {
      LoadingBar.clearTimer();
      instance = null;
      LoadingBar.destroy();
   },
}

结尾

其实不单单是 props 属性,你可以使用继承过来的 vue 对象的任意东西,怎么使用全凭各位的创造力啦~

(完)


本文为原创文章,可能会更新知识点及修正错误,因此转载请保留原出处,方便溯源,避免陈旧错误知识的误导,同时有更好的阅读体验 如果能给您带去些许帮助,欢迎 ⭐️star 或 ✏️ fork (转载请注明出处:https://chenjiahao.xyz)