- 前端
- UI组件
【免费下载链接】nprogress
For slim progress bars like on YouTube, Medium, etc
NProgress 是一个只有约 1KB 的极简进度条库,专为 Ajax 型应用设计,灵感来自 Google、YouTube 与 Medium 的顶部加载条。本文以仓库 Readme.md 为核心骨架,结合 nprogress.js、nprogress.css 与 test/test.js 的源码细节,系统讲解从安装引入、基础调用、Turbolinks/Pjax 集成,到进阶 API、八项配置项与样式自定义的完整实战方案,并深入剖析其“涓流递增(trickle)”动画的底层实现原理。读完本文,你将能独立在任何前端项目中接入、定制并理解 NProgress 的完整工作机制。
NProgress 是什么
NProgress 是一个极简(minimalist)的进度条库,官方定位为 “Minimalist progress bar”,专为 Ajax 型应用设计,受 Google、YouTube 和 Medium 等网站的顶部加载进度条启发。它只依赖两个文件:
- nprogress.js:核心逻辑,约 1000 行以内的纯 JavaScript 实现,无任何运行时依赖(jQuery 仅用于演示与测试页面);
- nprogress.css:样式与动画定义,体积同样十分精简。
从 package.json 可以看到,项目的dependencies为空,main字段指向nprogress.js,这意味着它可以直接在浏览器中以<script>标签方式引入,也可以通过 CommonJS / AMD / 全局变量三种方式加载(见 nprogress.js 的 UMD 包装)。
安装与引入
根据 Readme.md 的 Installation 章节,将 nprogress.js 与 nprogress.css 加入项目即可:
<script src='nprogress.js'></script> <link rel='stylesheet' href='nprogress.css'/>NProgress 同时支持 bower 与 npm 两种包管理方式安装:
$ npm install --save nprogress也可以直接通过 CDN 引入(以 0.2.0 版本为例,当前仓库 nprogress.js 中的NProgress.version即为0.2.0):
<script src='https://unpkg.com/nprogress@0.2.0/nprogress.js'></script> <link rel='stylesheet' href='https://unpkg.com/nprogress@0.2.0/nprogress.css'/>此外,bower.json 中声明了main: ["nprogress.js", "nprogress.css"],因此 bower 安装后同样只需引入这两个文件;component.json与package.json中的jspm/spm配置则保证了它还可以被 Component、JSPM、SPM 等模块体系直接使用。
基础用法:start() 与 done()
NProgress 的用法极其简单,只需调用start()和done()控制进度条:
NProgress.start(); NProgress.done();从源码看,start()会以NProgress.set(0)渲染进度条并立即进入涓流(trickle)自动递增模式,而done()内部实际上是NProgress.inc(0.3 + 0.5 * Math.random()).set(1)——先随机跳跃一段进度,再设置到 100% 并淡出移除,从而产生“逼真的运动感”(见 nprogress.js 的注释说明)。
仓库根目录的 index.html 就是一个完整的可运行示例:页面加载时调用NProgress.start(),1 秒后NProgress.done(),并提供了start、set(0.4)、inc()、done()四个演示按钮,可以直接打开体验实际效果。
与 Turbolinks / Pjax 集成
NProgress 最典型的应用场景是配合 Turbolinks 或 Pjax 这类“无刷新换页”技术,让用户在页面切换期间看到顶部进度条。
Turbolinks(5 及以上版本)
$(document).on('turbolinks:click', function() { NProgress.start(); }); $(document).on('turbolinks:render', function() { NProgress.done(); NProgress.remove(); });注意render事件回调中额外调用了NProgress.remove(),用于在页面渲染完成后立即把进度条 DOM 从页面中移除,避免残留。
Turbolinks(3 及以下版本)
要求 Turbolinks 1.3.0 以上:
$(document).on('page:fetch', function() { NProgress.start(); }); $(document).on('page:change', function() { NProgress.done(); }); $(document).on('page:restore', function() { NProgress.remove(); });Pjax
$(document).on('pjax:start', function() { NProgress.start(); }); $(document).on('pjax:end', function() { NProgress.done(); });这一系列集成模式的价值在于:进度条的生命周期完全由框架事件驱动,无需手工在业务代码里穿插进度更新逻辑。
更多应用想法
Readme 还给出了两个实用的扩展思路:
- 给所有 Ajax 调用加进度条:把
start()/done()绑定到 jQuery 的全局ajaxStart与ajaxStop事件,即可让页面上所有 Ajax 请求共享一条顶部进度条; - 即使没有 Turbolinks/Pjax 也能做出漂亮的加载条:把进度条绑定到
$(document).ready和$(window).load,模拟整页加载过程。
这两种方案都不需要修改 NProgress 本身,只需在你的业务代码中组织事件绑定即可。
进阶用法:set / inc / done(true) / status
设置百分比:.set(n)
set(n)接受0.0到1.0之间的数值,用于精确控制进度:
NProgress.set(0.0); // 相当于 .start() NProgress.set(0.4); NProgress.set(1.0); // 相当于 .done()从源码看,set()内部会对 n 做clamp(n, Settings.minimum, 1)处理,即下限被钳制为minimum配置值(默认 0.08),上限为 1;当 n 为 1 时,NProgress.status会被置回null表示“未开始”,并执行淡出与移除流程(nprogress.js)。这一点在 test/test.js 中有对应测试:set(0)后 status 等于settings.minimum,set(-100)同样被钳制到 minimum,set(456)则视为完成。
递增:.inc()
.inc()以随机增量推进进度条,永远不会到达 100%,适合配合“每张图片加载完成”之类的场景使用:
NProgress.inc();也可以传入明确的增量值:
NProgress.inc(0.2); // 在当前 status 基础上加 0.2,上限 0.994从 nprogress.js 的源码可以看到无参inc()的“涓流”算法:进度在 0~0.2 区间时每次递增 0.1,0.2~0.5 区间递增 0.04,0.5~0.8 区间递增 0.02,0.8~0.99 区间递增 0.005,越接近完成增量越小,最后统一clamp(n + amount, 0, 0.994)——永远不会到 1。测试 test/test.js 也验证了连续调用 100 次inc()后 status 依然小于 1.0。
强制完成:.done(true)
默认情况下,如果从未调用过start(),调用done()不会做任何事情(源码中if (!force && !NProgress.status) return this;)。传入true则可以强制显示并完成进度条:
NProgress.done(true);读取当前状态:.status
通过NProgress.status可以随时读取当前进度值。源码中status初始为null,一旦set()被调用就成为0.08~1.0之间的数字,完成(n===1)后又回到null;isStarted()正是通过typeof NProgress.status === 'number'来判断进度条是否已启动。
配置详解:configure 的八项参数
所有配置都通过NProgress.configure({ ... })设置。源码中这些配置集中定义在NProgress.settings对象里(nprogress.js),configure()会把传入对象中所有非 undefined 的键值合并进 settings(nprogress.js)。下表汇总了全部配置项、默认值与作用:
| 配置项 | 默认值 | 说明 |
|---|---|---|
minimum | 0.08 | 起始时的最小百分比 |
template | 默认 bar + spinner 模板 | 自定义进度条 DOM 结构 |
easing | linear(Readme 示例中为ease) | CSS 缓动函数字符串 |
speed | 200 | 动画时长(毫秒) |
trickle | true | 是否开启自动递增 |
trickleSpeed | 200 | 自动递增的间隔(毫秒) |
showSpinner | true | 是否显示右侧加载圈 |
parent | body | 进度条的父容器 |
minimum:起始最小百分比
NProgress.configure({ minimum: 0.1 });minimum会在set()/start()时把初始进度钳制到该值以上,避免进度条从 0 突兀开始。测试 test/test.js 验证了configure({ minimum: 0.5 })能正确写入 settings。
template:自定义 DOM 模板
NProgress.configure({ template: "<div class='....'>...</div>" });使用template可以完全替换进度条的 DOM 结构,但为了让进度条正常工作,模板中必须保留一个role='bar'的元素。默认模板定义在源码中(nprogress.js):
<div class="bar" role="bar"><div class="peg"></div></div><div class="spinner" role="spinner"><div class="spinner-icon"></div></div>render()会把模板注入#nprogress容器,并通过barSelector: '[role="bar"]'和spinnerSelector: '[role="spinner"]'两个选择器定位 bar 与 spinner 元素(nprogress.js),所以自定义模板时保证role属性不变即可。
easing与speed:动画设置
NProgress.configure({ easing: 'ease', speed: 500 });easing是 CSS 缓动字符串(Readme 示例为ease,源码默认值是linear),speed是动画时长(毫秒,默认 200)。二者会拼接成transition: 'all ' + speed + 'ms ' + ease应用到 bar 元素上(nprogress.js),控制进度条每次位移的过渡效果。
trickle:关闭自动递增
NProgress.configure({ trickle: false });trickle默认true,此时start()会启动一个以trickleSpeed为间隔的递归定时器不断调用trickle()(即无参inc()),模拟真实的加载过程(nprogress.js)。设为false后,进度只会在你显式调用set()/inc()时变化,适合需要完全手动控制进度的场景。
trickleSpeed:递增间隔
NProgress.configure({ trickleSpeed: 200 });控制自动递增的频率,单位毫秒,默认 200ms。在start()的定时器中,每次回调都会先检查NProgress.status是否仍存在,若进度条已被done()移除则自动终止递归,避免内存泄漏。
showSpinner:关闭加载圈
NProgress.configure({ showSpinner: false });默认true,会在页面右上角显示一个 18×18 的旋转圆圈(样式见 nprogress.css)。设为false后,render()会直接把模板中的 spinner 元素从 DOM 移除(nprogress.js)。测试 test/test.js 验证了默认渲染 spinner、配置false后不渲染。
parent:更换父容器
NProgress.configure({ parent: '#container' });默认进度条固定在body上(position: fixed,见 nprogress.css)。指定parent后,进度条会被插入该容器内,同时容器会获得nprogress-custom-parent类,CSS 中对应规则会把 bar 和 spinner 改为position: absolute,使其跟随容器滚动而非固定在视口顶部(nprogress.css)。测试 test/test.js 验证了configure({parent: '#test'})后进度条确实挂载到#test下且父容器带上了nprogress-custom-parent类。parent既支持 CSS 选择器字符串,也支持直接传入 DOM 元素(isDOM()检测,见 nprogress.js)。
自定义样式:改 nprogress.css
Readme 的 Customization 章节指出,只需按需编辑 nprogress.css 即可;最常用的做法是全局查找并替换主题色#29d。这个颜色在样式表中共出现在 4 处:
- bar 的背景色(nprogress.css);
- 右侧
peg拖尾元素的模糊光晕box-shadow(nprogress.css); - spinner 圆圈的
border-top-color与border-left-color(nprogress.css)。
从结构上看,默认进度条由三部分组成:顶部 2px 高的蓝色bar、bar 右端 100px 宽带有发光效果的旋转peg拖尾、以及右上角旋转的spinner。Readme 强调“自带的 CSS 非常精简,完全可以弃用并自行编写”,因此你可以自由决定是否保留 peg 光晕、spinner,甚至改用完全不同的视觉呈现——只要 JS 端的模板与role约定保持一致即可。
源码原理:NProgress 是如何工作的
渲染与移除
render()是核心渲染函数:先检查document.getElementById('nprogress')是否已存在(isRendered()),不存在则在<html>上添加nprogress-busy类、创建#nprogress容器并注入模板。首次渲染时 bar 的位移被设为translate3d(-100%,0,0)(完全移出视口),之后每次set()都通过queue队列串行执行位移动画(nprogress.js)。remove()则负责移除nprogress-busy与nprogress-custom-parent类并删除 DOM(nprogress.js)。
兼容性处理:三种位移策略
getPositioningCSS()(nprogress.js)会在首次使用时嗅探浏览器能力,从三种位移方案中选择:
translate3d:支持 3D 变换的现代浏览器(如 WebKit、IE10+);translate:不支持 3D 但支持 transform 的浏览器(如 IE9);margin:两者都不支持的老旧浏览器(如 IE7-8),退化为修改margin-left。
动画队列
进度条的每次移动都通过内部queue函数串行排队执行,保证快速连续调用set()时动画按顺序完成,不会互相打断(nprogress.js)。
Promise 支持
除了 Readme 中介绍的 API,源码还内置了NProgress.promise($promise)(nprogress.js):传入 jQuery Promise 后会自动start(),并随 Promise 的 resolve 进度逐步set(),全部完成后自动done()。这为“多请求并行、统一进度展示”提供了开箱即用的方案。
测试验证
仓库使用 Mocha + Chai + jsdom 编写了覆盖核心 API 的测试(test/test.js),运行方式为npm test(见 package.json 的 scripts)。测试覆盖了set()的渲染与钳制、start()的最小值与 parent 挂载、done()的 force 行为、remove()的清理、inc()的递增与永不触顶、以及configure()与showSpinner等关键行为,是理解 NProgress 各 API 语义的最佳参考。
小结
NProgress 的价值在于:以最小的体积和最简单的 API(start()/done()两个方法即可驱动),为 Ajax 型应用提供一条足够“真实”的顶部进度条。本文从 Readme.md 出发,完整覆盖了安装引入、基础/进阶用法、Turbolinks/Pjax 集成、八项配置参数与样式定制,并结合 nprogress.js 源码剖析了涓流递增算法、渲染队列、位移降级与 Promise 支持等底层机制。实际接入时只需记住三条铁律:保留模板中的role='bar'、用configure()调整行为、用nprogress.css控制外观——其余交给 NProgress 即可。
- 前端
- UI组件
【免费下载链接】nprogress
For slim progress bars like on YouTube, Medium, etc
相关推荐
VuePress 官方 nprogress 插件(@vuepress/plugin-nprogress)完全指南:原理、安装与自定义进度条
VuePress 官方 nprogress 插件(@vuepress/plugin nprogress)完全指南:原理、安装与自定义进度条 本文以 VuePre
前端文档SSRVuePress 官方 nprogress 进度条插件:安装、配置与路由加载进度条原理剖析
VuePress 官方 nprogress 进度条插件:安装、配置与路由加载进度条原理剖析 导读 @vuepress/plugin nprogress 是 Vu
前端文档SSRVuePress nprogress 插件指南:为页面跳转添加顶部进度条
VuePress nprogress 插件指南:为页面跳转添加顶部进度条 本指南聚焦 VuePress 官方插件 @vuepress/plugin nprogr
前端文档SSR
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考