Nprogress是一個比較簡單的頁面加載用進度條(其實也可以用作接口加載進度,或者其它處理加載進度樣式)。簡單而代碼又少。實用度比較高。
1、Nprogress的原理
Nprogress的原理非常簡單,就是頁面啓動的時候,構建一個方法,創建一個div,然後這個div靠近最頂部,用fixed定位住,至於樣式就是按照自個或者默認走了。
相信很多小夥伴都知道,一個頁面或者一個接口的進度計算是非常複雜的,即便能夠計算出來,那麼消耗的性能終究是非常大的,這個時候虛假的進度條的作用就顯示它的強大了。一開始進入處理方法的時候,它就啓動loading的效果,一旦捕獲到這個方法結束的時候,那麼就釋放它,爲了防止比較生硬,那麼釋放後也會有一個進度條緩慢加載完成100%。
2、Nprogress源碼
看什麼都需要看最終的代碼,這樣我們纔不會別人的分析所“一葉蔽目”。
github地址:https://github.com/rstacruz/nprogress
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' //這個樣式必須引入
以上。