在Vue3项目中,一个运行中的进度条能显著提升用户体验,尤其适合长耗时请求或页面切换场景。NProgress作为轻量级进度条库,搭配TypeScript和Vite环境,可优雅地融入现有项目。下面分享一套经过验证的集成方案,涵盖基础安装、可配置Hook封装、Axios拦截器和Vue Router守卫集成,以及全局样式自定义。
一、环境准备
首先安装核心依赖和类型定义:- pnpm i nprogress lodash-es
- pnpm i @types/nprogress @types/lodash-es -D
复制代码 nprogress提供进度控制API,lodash-es用于对象深度合并。类型声明仅在开发时使用。
通过环境变量控制进度条开关,在.env文件中加入:- VITE_ROUTER_NPROGRESS = true
- VITE_REQUEST_NPROGRESS = true
复制代码 设置为'false'即可关闭对应场景的进度条,无需修改代码。
二、核心封装:useProgress Hook
创建一个可复用的组合式函数,统一配置进度条行为。- // src/hooks/useProgress.ts
- import { merge } from 'lodash-es'
- import NProgress from 'nprogress'
- import type { NProgressOptions } from 'nprogress'
- interface ProgressConfig extends NProgressOptions {
- show: boolean
- }
- const DEFAULT_CONFIG: Partial<ProgressConfig> = {
- easing: 'ease',
- parent: 'body',
- show: true,
- showSpinner: false,
- trickle: true,
- minimum: 0.08,
- speed: 200,
- }
- export function useProgress(config: Partial<ProgressConfig> = {}) {
- const mergeConfig = merge({}, DEFAULT_CONFIG, config)
- NProgress.configure(mergeConfig)
- function start() {
- if (!mergeConfig.show) return
- NProgress.start()
- }
- function done() {
- if (!mergeConfig.show || !NProgress.isStarted()) return
- NProgress.done()
- }
- return { start, done }
- }
复制代码 该Hook接受自定义配置,与默认配置深度合并后调用NProgress.configure。start和done方法根据show属性决定是否实际执行,避免因环境变量关闭带来的无谓调用。
三、实际应用场景
1. Axios请求拦截器集成
创建通用请求模块,在请求发送前启动进度条,请求完成后结束。- // src/utils/request.ts
- import axios from 'axios'
- import { useProgress } from '@/hooks/useProgress'
- const NProgress = useProgress({ show: import.meta.env.VITE_REQUEST_NPROGRESS !== 'false' })
- const instance = axios.create({
- baseURL: import.meta.env.VITE_API_BASE_URL,
- timeout: 15000,
- })
- instance.interceptors.request.use(
- (config) => {
- NProgress.start()
- return config
- },
- (error) => {
- NProgress.done()
- return Promise.reject(error)
- }
- )
- instance.interceptors.response.use(
- (response) => {
- NProgress.done()
- return response
- },
- (error) => {
- NProgress.done()
- return Promise.reject(error)
- }
- )
- export const request = instance
复制代码 注意:在请求或响应错误时也要调用done,防止进度条卡住。
2. Vue Router路由守卫集成
在路由切换时自动显示进度条,通过环境变量控制。- // src/router/index.ts
- import { createRouter, createWebHistory } from 'vue-router'
- import { useProgress } from '@/hooks/useProgress'
- const router = createRouter({
- history: createWebHistory(),
- routes: [],
- })
- const NProgress = useProgress({ show: import.meta.env.VITE_ROUTER_NPROGRESS !== 'false' })
- router.beforeEach((to, from, next) => {
- NProgress.start()
- next()
- })
- router.afterEach(() => {
- NProgress.done()
- })
- export default router
复制代码 若使用了异步路由,确保在路由解析完成后执行done,避免过早结束。
3. 组合式调用示例
在Vue组件的任何异步操作中也可手动调用:- <script setup lang="ts">
- import { useProgress } from '@/hooks/useProgress'
- const NProgress = useProgress({ show: import.meta.env.VITE_REQUEST_NPROGRESS !== 'false' })
- async function loadData() {
- NProgress.start()
- try {
- await fetch('/api/data')
- } finally {
- NProgress.done()
- }
- }
- </script>
复制代码 务必使用try...finally确保进度条能正确结束。
四、全局样式自定义
NProgress默认提供朴素样式,通常需与项目主题匹配。推荐在全局样式入口文件中覆盖。
创建src/styles/nprogress.scss,定义渐变色进度条:- // src/styles/nprogress.scss
- #nprogress .bar {
- background: var(--el-color-primary);
- height: 3px;
- background: linear-gradient(90deg, var(--el-color-primary-light-3) 0%, var(--el-color-primary) 100%);
- }
- #nprogress .peg {
- box-shadow: 0 0 10px var(--el-color-primary);
- }
- #nprogress .spinner-icon {
- border-top-color: var(--el-color-primary);
- border-left-color: var(--el-color-primary);
- }
复制代码 然后新建src/styles/index.scss,统一导入:- @use 'nprogress.scss';
- @use 'variables.scss';
- @use 'transition.scss';
- @use 'element-plus/el-table.scss';
- @use 'element-plus/el-dialog.scss';
- @use 'element-plus/el-dropdown.scss';
- body {
- font-family: var(--el-font-family);
- background-color: var(--el-bg-color-page);
- }
复制代码 最后在main.ts引入:- import { createApp } from 'vue'
- import App from './App.vue'
- import './styles/index.scss'
- const app = createApp(App)
- app.mount('#app')
复制代码 注意:如果有其他样式文件,顺序需处理好。若不需要自定义,也可以直接引入nprogress自带的CSS:- @use 'nprogress/nprogress.css';
复制代码
五、NProgress配置项详解
配置项支持以下参数(配置通过NProgress.configure传入):
- {
- easing: 'ease', // CSS3缓动函数
- speed: 200, // 动画速度(ms)
- trickle: true, // 是否自动递增
- trickleSpeed: 200, // 自动递增速度
- minimum: 0.08, // 起始百分比(0-1)
- showSpinner: false, // 是否显示环形加载动画
- parent: 'body', // 父容器CSS选择器
- positionUsing: '', // 定位方式(可选'absolute','fixed'等)
- }
复制代码 缓动函数推荐使用标准值或自定义贝塞尔曲线,例如:- const EASING_FUNCTIONS = {
- linear: 'linear',
- ease: 'ease',
- smooth: 'cubic-bezier(0.4, 0, 0.2, 1)',
- gentle: 'cubic-bezier(0.25, 0.1, 0.25, 1)',
- swift: 'cubic-bezier(0.4, 0, 0.6, 1)',
- }
复制代码 可根据项目视觉风格灵活调整。
以上方案已在多个Vue3+TypeScript项目中使用,通过环境变量和配置Hook,能轻松控制进度条的显示与行为,并与Axios、Vue Router深度整合。希望这套封装能帮你快速落地NProgress,提升应用的用户反馈体验。 |