vue导航守卫配合nprogress实现加载进度条:beforeeach中调用start()启动,aftereach中调用done()收尾;懒加载时可通过预加载模拟进度;需防重复触发、引入css样式并适配移动端容器。

Vue 导航守卫是控制路由跳转生命周期的关键机制,在单页应用中配合进度条插件(如 NProgress)展示加载特效,核心在于利用 beforeEach 和 afterEach 守卫精准触发进度条的启动与结束。
用 beforeEach 启动进度条
在用户点击链接或调用 router.push 后、目标组件尚未开始加载前,beforeEach 会立即执行。此时调用 NProgress.start() 即可显示进度条。
- 避免在守卫里直接写逻辑判断是否跳转(如权限校验),否则可能阻塞进度条启动;确需异步校验时,应在 resolve 前调用 start
- 若页面已存在缓存(如 keep-alive),部分跳转会跳过组件销毁重建,但守卫仍会触发,进度条依然生效
- 不建议在此阶段手动设置进度值(如
NProgress.set(0.3)),因为真实加载尚未开始,容易造成感知失真
用 afterEach 确保进度条收尾
afterEach 在导航成功完成、新页面 DOM 渲染完毕后执行,适合调用 NProgress.done() 隐藏进度条。
- 它不接收 next 参数,也不影响路由流程,纯属“收尾钩子”,安全性高
- 即使目标路由组件抛出渲染错误(如 setup 报错),
afterEach仍会执行,避免进度条卡死 - 注意:如果页面内有异步数据获取(如
onMounted中发请求),done()不会等待这些请求完成——这是预期行为;如需同步数据加载状态,应另配请求拦截器
配合懒加载 chunk 实现更真实的进度估算
当路由组件采用异步 import(即懒加载)时,Webpack/Vite 会将其拆分为独立 chunk。NProgress 虽不能读取真实字节进度,但可通过预加载 + Promise.race 模拟区间进度。
- 在
beforeEach中,对目标路由的import()执行vitePreload(Vite)或import.meta.webpackModuleId(Webpack),触发预加载 - 用
Promise.race([preloadPromise, actualImportPromise])获取首个完成的 Promise,以此估算当前 chunk 加载阶段 - 该方式仅在构建后生效;开发环境热更新会绕过 chunk 分离,进度条将退化为匀速模拟
避免常见陷阱
进度条体验是否自然,往往取决于细节处理:
- 重复触发:同一导航中多次调用
start()不会报错,但可能导致进度重置;建议在beforeEach开头加NProgress.isStarted() && NProgress.done()防兜底 - CSS 样式未加载:必须在入口文件(如 main.ts)中显式引入
nprogress/nprogress.css,否则只有 JS 行为无视觉效果 - 移动端适配:NProgress 默认挂载到
body,若项目使用了 fixed 定位的顶部导航栏,需通过parent配置指定相对容器,避免遮挡
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










