- 前端
【免费下载链接】vueuse
Collection of essential Vue Composition Utilities for Vue 3
useNProgress是 VueUse Integrations 系列中对nprogress的响应式封装,让你以 Vue 原生的 Ref 语法驱动经典的顶部细进度条。本文基于 VueUse 仓库中 useNProgress 的参考文档 与 源码实现,完整讲解安装、基础用法、进度百分比控制与样式定制,并结合源码剖析其响应式联动原理。读完本文,你将掌握如何用寥寥几行代码为路由切换、异步请求等场景接入一个可声明式控制的进度条。
背景:为什么需要响应式封装
nprogress是一个轻量、无依赖的顶部进度条库,其核心 API 是命令式的start()、done()、set(n)与configure(options)。在 Vue 3 的组合式 API 语境下,命令式调用难以与模板、watch等响应式机制直接联动。useNProgress的做法是把命令式 API 包装成Ref与WritableComputedRef,让进度状态成为组件数据流的一部分。在 VueUse 仓库中它位于 Integrations 包内,并由 packages/integrations/index.ts 统一导出。
安装与依赖说明
useNProgress是一个集成封装,本身不打包nprogress,因此需要单独安装:
npm i nprogress@^0如果使用 pnpm,还可一并安装类型声明:
pnpm add nprogress@^0 pnpm add -D @types/nprogress在 packages/integrations/package.json 中,nprogress被声明为可选 peer 依赖("nprogress": "^0.2",并在peerDependenciesMeta中标记optional: true),意味着你只在使用该函数时才需要安装它,不会强制拖入无关依赖。
基础用法:声明式开关 isLoading
使用方式非常直接——从@vueuse/integrations/useNProgress子路径导入:
import { useNProgress } from '@vueuse/integrations/useNProgress' const { isLoading } = useNProgress() function toggle() { isLoading.value = !isLoading.value }isLoading是一个WritableComputedRef<boolean, boolean>:把isLoading.value置为true会调用nprogress.start()让进度条开始流动,置为false则调用nprogress.done()让进度条收尾并淡出。因此在模板中可以直接绑定:
<button @click="isLoading = !isLoading"> {{ isLoading ? 'Stop' : 'Start' }} </button>这段写法的演示可参见仓库中的 useNProgress/demo.vue,它还展示了配合progress实时显示百分比:
<b v-if="isLoading" class="ml-2">{{ ((progress || 0) * 100).toFixed(0) }}%</b>底层联动原理
从源码 packages/integrations/useNProgress/index.ts 可以看到isLoading的完整定义:
const isLoading = computed({ set: load => load ? nprogress.start() : nprogress.done(), get: () => typeof progress.value === 'number' && progress.value < 1, })get的判定逻辑是:只有当progress是数字且小于1时才算"加载中"。这与nprogress的语义一致——进度到达1即表示完成。由此isLoading既能手动写入(驱动进度条),也能从当前进度反推出加载状态(供模板展示),实现双向联动。
控制进度百分比:progress Ref
useNProgress的第一个参数用于传入初始进度,支持数字、Ref或 getter 函数(MaybeRefOrGetter<number | null | undefined>):
const { progress } = useNProgress(0.5) function done() { progress.value = 1.0 }要改变进度百分比,只需设置progress.value = n,其中n是0..1之间的数字。默认参数为null,表示进度条处于"未知进度"的流动状态。
源码中的同步机制
源码对进度的同步做了两层处理(packages/integrations/useNProgress/index.ts):
const setProgress = nprogress.set nprogress.set = (n: number) => { progress.value = n return setProgress.call(nprogress, n) } watchEffect(() => { if (typeof progress.value === 'number' && isClient) setProgress.call(nprogress, progress.value) })- 第一处:拦截并重写
nprogress.set。当nprogress内部因自动递增而更新进度时,同步写回progress.value,保证 Ref 始终反映真实进度; - 第二处:
watchEffect反向驱动。当外部修改progress.value为数字时,调用底层的set把进度推给nprogress,且通过isClient(来自@vueuse/shared)在服务端渲染时跳过 DOM 操作,保证 SSR 安全。
这种双向同步正是"响应式封装"的核心价值:无论进度来自手动赋值、路由守卫还是nprogress内部逻辑,progressRef 都能保持一致。
配置项:第二个参数 options
可以通过第二个参数传入配置对象来定制行为,例如设置进度条的最小初始值:
import { useNProgress } from '@vueuse/integrations/useNProgress' useNProgress(null, { minimum: 0.1, // 其他 nprogress 配置项 })options的类型是UseNProgressOptions = Partial<NProgressOptions>(packages/integrations/useNProgress/index.ts),即nprogress全部配置项的浅层可选子集,常见可用项包括:
| 配置项 | 作用 | 典型值 |
|---|---|---|
minimum | 起始最小进度,避免刚启动就跳到过高的百分比 | 0.08起,示例中使用0.1 |
easing | 进度条运动的缓动函数名 | 'ease'、'linear' |
speed | 进度条动画速度(毫秒) | 200 |
trickle | 是否启用自动递增的小步前进 | true |
trickleSpeed | 自动递增的时间间隔(毫秒) | 200 |
showSpinner | 是否显示右上角旋转加载圈 | true/false |
parent | 进度条挂载的父容器元素 | 'body'或某个 DOM 元素 |
这些配置会通过nprogress.configure(options)一次性应用到全局(packages/integrations/useNProgress/index.ts),因此适合在应用初始化时统一配置。
样式定制
进度条的外观由nprogress自带的 CSS 控制。最直接的做法是修改nprogress.css中你喜欢的部分——通常只需查找并替换主题色#29d(nprogress 的默认蓝色)即可。
仓库中的示例 useNProgress/style.css 提供了一套可参考的自定义样式:它把主色替换为绿色#67d391,保留#nprogress上pointer-events: none(让点击事件穿透进度条),并为进度条.bar设置了position: fixed、z-index: 1031、top: 0、height: 2px的顶部细条布局,同时用.peg的box-shadow实现右侧发光拖尾效果。在自己的项目中,引入自定义样式的方式与 demo 一致:
import { useNProgress } from '@vueuse/integrations/useNProgress' import './style.css'如果需要把进度条限制在某个局部容器内(而不是全屏顶部),可以配合parent配置项指定容器,并给容器添加nprogress-custom-parent类(样式文件中有对应的绝对/相对定位规则)。
返回的完整 API
useNProgress返回一个包含五个成员的对象(packages/integrations/useNProgress/index.ts):
export interface UseNProgressReturn { isLoading: WritableComputedRef<boolean, boolean> progress: Ref<number | null | undefined> start: () => NProgress done: (force?: boolean) => NProgress remove: () => void }| 成员 | 类型 | 说明 |
|---|---|---|
isLoading | WritableComputedRef<boolean> | 读写双向:置true调用start(),置false调用done();读取时按progress < 1判断 |
progress | Ref<number \| null \| undefined> | 当前进度百分比(0..1),可读可写 |
start | () => NProgress | 启动进度条(透传自nprogress.start) |
done | (force?: boolean) => NProgress | 结束进度条,force为true时强制立即完成 |
remove | () => void | 移除进度条 DOM,同时将progress重置为null |
注意done(force)支持一个可选的force参数:传true时跳过淡出动画,立即移除进度条。而remove的语义更彻底——源码中它同时把progress.value重置为null并调用nprogress.remove()(packages/integrations/useNProgress/index.ts),适合在组件卸载或需要彻底清除进度条时使用。
生命周期自动清理
一个值得关注的细节:源码在函数末尾调用了tryOnScopeDispose(nprogress.remove)(packages/integrations/useNProgress/index.ts)。
tryOnScopeDispose来自@vueuse/shared(导出见 packages/shared/index.ts),它的语义是:如果当前存在活跃的 effect scope(如组件实例或手动effectScope),就在作用域销毁时自动执行清理回调;否则直接忽略。这意味着当使用useNProgress的组件被卸载,或包裹它的effectScope被释放时,进度条会自动移除,无需手动清理,避免进度条残留在页面上或产生内存泄漏。
典型应用场景
把以上能力组合起来,最常见的落地场景是路由级加载指示。以 Vue Router 为例,在全局前置守卫中结合isLoading即可实现"跳转期间显示进度条":
import { useNProgress } from '@vueuse/integrations/useNProgress' const { isLoading, done } = useNProgress(null, { showSpinner: false }) router.beforeEach(() => { isLoading.value = true }) router.afterEach(() => { done() })异步请求场景中,也可以用progress精确反映上传/下载进度,或对多个并行请求统一以start/done收口。由于isLoading、progress都是标准的响应式引用,它们天然可以放进watch、计算属性或组件模板中,与 Vue 3 的组合式 API 生态无缝衔接。
小结
useNProgress是nprogress的响应式薄封装,核心价值在于把命令式 API 转换为isLoading/progress两个响应式引用,并保持双向同步;- 安装时需单独引入
nprogress(可选 peer 依赖),样式可参考 style.css 自定义,配置通过第二个参数传入; - 通过重写
nprogress.set与watchEffect实现进度双向同步,借助tryOnScopeDispose实现组件卸载自动清理; - 官方参考文档 useNProgress.md 与源码 index.ts、demo.vue 可直接对照阅读,是理解该函数最权威的第一手资料。
- 前端
【免费下载链接】vueuse
Collection of essential Vue Composition Utilities for Vue 3
相关推荐
VueUse useNProgress:在 Vue 3 中响应式驱动 nprogress 顶部进度条
VueUse useNProgress:在 Vue 3 中响应式驱动 nprogress 顶部进度条 useNProgress 是 VueUse Integra
前端在 airi 中集成 VueUse useNProgress:从响应式进度条到路由加载指示实战
在 airi 中集成 VueUse useNProgress:从响应式进度条到路由加载指示实战 useNProgress 是 VueUse 生态中针对 npro
AI 应用人工智能大模型数字人AI Agent语音前端后端桌面应用移动开发即时通讯3D渲染VueUse useGamepad 实战:在 Vue 3 应用中响应式接入 Gamepad API(Airi 仓库参考指南)
VueUse useGamepad 实战:在 Vue 3 应用中响应式接入 Gamepad API(Airi 仓库参考指南) 本文基于 Airi 开源仓库中的
AI 应用人工智能大模型数字人AI Agent语音前端后端桌面应用移动开发即时通讯3D渲染
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考