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' //这个样式必须引入
以上。