Nprogress——页面加载的虚假进度条

Nprogress是一个比较简单的页面加载用进度条(其实也可以用作接口加载进度,或者其它处理加载进度样式)。简单而代码又少。实用度比较高。
1、Nprogress的原理
Nprogress的原理非常简单,就是页面启动的时候,构建一个方法,创建一个div,然后这个div靠近最顶部,用fixed定位住,至于样式就是按照自个或者默认走了。
相信很多小伙伴都知道,一个页面或者一个接口的进度计算是非常复杂的,即便能够计算出来,那么消耗的性能终究是非常大的,这个时候虚假的进度条的作用就显示它的强大了。一开始进入处理方法的时候,它就启动loading的效果,一旦捕获到这个方法结束的时候,那么就释放它,为了防止比较生硬,那么释放后也会有一个进度条缓慢加载完成100%。
2、Nprogress源码
看什么都需要看最终的代码,这样我们才不会别人的分析所“一叶蔽目”。
github地址:https://github.com/rstacruz/nprogress


Nprogressgithub展示
nprogress.js是它主要的方法,这里就不展示全部代码了,暴露常用的方法是NProgress.start和NProgress.done。而这两个方法都跟着NProgress.set一起走。其实我们主要的就是要研究透NProgress.set方法。
NProgress.start如下:

 /**
   * Shows the progress bar.
   * This is the same as setting the status to 0%, except that it doesn't go backwards.
   *
   *     NProgress.start();
   *
   */
  NProgress.start = function() {
    if (!NProgress.status) NProgress.set(0);

    var work = function() {
      setTimeout(function() {
        if (!NProgress.status) return;
        NProgress.trickle();
        work();
      }, Settings.trickleSpeed);
    };

    if (Settings.trickle) work();

    return this;
  };

NProgress.done代码如下:

/**
   * Hides the progress bar.
   * This is the *sort of* the same as setting the status to 100%, with the
   * difference being `done()` makes some placebo effect of some realistic motion.
   *
   *     NProgress.done();
   *
   * If `true` is passed, it will show the progress bar even if its hidden.
   *
   *     NProgress.done(true);
   */

  NProgress.done = function(force) {
    if (!force && !NProgress.status) return this;

    return NProgress.inc(0.3 + 0.5 * Math.random()).set(1);
  };

NProgress.set代码如下:

/**
   * Sets the progress bar status, where `n` is a number from `0.0` to `1.0`.
   *
   *     NProgress.set(0.4);
   *     NProgress.set(1.0);
   */

  NProgress.set = function(n) {
    var started = NProgress.isStarted();

    n = clamp(n, Settings.minimum, 1);
    NProgress.status = (n === 1 ? null : n);

    var progress = NProgress.render(!started),
        bar      = progress.querySelector(Settings.barSelector),
        speed    = Settings.speed,
        ease     = Settings.easing;

    progress.offsetWidth; /* Repaint */

    queue(function(next) {
      // Set positionUsing if it hasn't already been set
      if (Settings.positionUsing === '') Settings.positionUsing = NProgress.getPositioningCSS();

      // Add transition
      css(bar, barPositionCSS(n, speed, ease));

      if (n === 1) {
        // Fade out
        css(progress, {
          transition: 'none',
          opacity: 1
        });
        progress.offsetWidth; /* Repaint */

        setTimeout(function() {
          css(progress, {
            transition: 'all ' + speed + 'ms linear',
            opacity: 0
          });
          setTimeout(function() {
            NProgress.remove();
            next();
          }, speed);
        }, speed);
      } else {
        setTimeout(next, speed);
      }
    });

    return this;
  };

其它比较重要的代码:

/**
   * Increments by a random amount.
   */

  NProgress.inc = function(amount) {
    var n = NProgress.status;

    if (!n) {
      return NProgress.start();
    } else if(n > 1) {
      return;
    } else {
      if (typeof amount !== 'number') {
        if (n >= 0 && n < 0.2) { amount = 0.1; }
        else if (n >= 0.2 && n < 0.5) { amount = 0.04; }
        else if (n >= 0.5 && n < 0.8) { amount = 0.02; }
        else if (n >= 0.8 && n < 0.99) { amount = 0.005; }
        else { amount = 0; }
      }

      n = clamp(n + amount, 0, 0.994);
      return NProgress.set(n);
    }
  };

  NProgress.trickle = function() {
    return NProgress.inc();
  };

NProgress.start很明显就是进度条创造的开始,如果已经创建了,那么自然就return出去不让在读进入方法。而work()方法就是一个具体的方法,在setTimeout中轮询,这里边有一个NProgress.trickle();也就是NProgress.inc方法就是一些简单的算法。
首先

var n = NProgress.status;

这是一个进度条,其次就是分段判断了,

if (!n) {
      return NProgress.start();
    } else if(n > 1) {
      return;
    } else {
      if (typeof amount !== 'number') {
        if (n >= 0 && n < 0.2) { amount = 0.1; }
        else if (n >= 0.2 && n < 0.5) { amount = 0.04; }
        else if (n >= 0.5 && n < 0.8) { amount = 0.02; }
        else if (n >= 0.8 && n < 0.99) { amount = 0.005; }
        else { amount = 0; }
      }

      n = clamp(n + amount, 0, 0.994);
      return NProgress.set(n);
    }

clamp是一个方法,判断大小用,代码如下:

function clamp(n, min, max) {
    if (n < min) return min;
    if (n > max) return max;
    return n;
  }

NProgress.done就是进度条达到100%。传入了1。
这个时候:

// Fade out
        css(progress, {
          transition: 'none',
          opacity: 1
        });
        progress.offsetWidth; /* Repaint */

        setTimeout(function() {
          css(progress, {
            transition: 'all ' + speed + 'ms linear',
            opacity: 0
          });
          setTimeout(function() {
            NProgress.remove();
            next();
          }, speed);
        }, speed);

样式由opacity1慢慢变成opacity0,并且进度条在慢慢变成100%(),transition: 'all ’ + speed + ‘ms linear’,就是用来控制translate3d的x轴的。

3、vue中引用
nodejs的npm安装如下:

$ npm install --save nprogress

vue的话,比较常用的方式是路由加载的router.beforeEach中加NProgress.start();
在router.afterEach中加NProgress.end();

在引入的时候,需要注意,css也必须引入:

import NProgress from "nprogress"
import 'nprogress/nprogress.css' //这个样式必须引入

以上。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章