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' //這個樣式必須引入

以上。

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