使用NProgress为页面/接口添加加载进度条
当你打开一个页面,页面显示空白或者部分空白,那么用户就会怀疑你的网页是不是有问题。我们需要让我们的用户知道数据在路上,当他们点击一个需要请求数据链接时,就会给出反馈,让用户知道页面的加载情况
一、NProgress(一个轻量级进度条组件)
1. 借用axios拦截器组合实现
2. 通过组件内的路由守卫实现
3. 通过路由的全局前置守卫实现
二、解决方案1:NProgress 与 axios interceptors
1)安装NProgress
1 $ npm install nprogress
2) 安装好之后,需要在main.js中引入CSS
1 import 'nprogress/nprogress.css'
3) 最后在axios中引入NProgress
1 import NProgress from 'nprogress'
NProgress提供四个基本API
1 NProgress.start()// 开始展示进度条 2 NProgress.set(0.4)// 设置进度百分比 3 NProgress.inc()// 以随机量递增进度 4 NProgress.done()// 完成进度条 5 // 配置进度条 6 NProgress.configure({ 7 minimum: 0.08, // 配置开始初始值,默认0.08 8 template: ` 9 <div class="bar" role="bar"> 10 <div class="peg"></div> 11 </div> 12 <div class="spinner" role="spinner"> 13 <div class="spinner-icon"></div> 14 </div> 15 `, // 配置模板 16 easing: 'linear', // 配置动画 17 speed: 200, //配置速度 18 trickle: true, // 是否让进度条自动增加 19 trickleSpeed: 200, // 配置自动前进的频率ms 20 showSpinner: true, //是否显示加载动画,如下图 21 parent: 'body' //配置挂载元素,即相对定位的元素 22 })
AXIOS拦截器允许我们拦截我们的请求和响应,添加额外的功能,我们可以在其中启动和停止进度条,一个简单的功能如下所示:
1 axios.interceptors.request.use(config => { 2 NProgress.start() 3 return config 4 }) 5 axios.interceptors.response.use(response => { 6 NProgress.done() 7 return response 8 })
正如您所看到的,AXIOS拦截器充当中间件,允许您在发出请求时或在接收到响应时运行某些代码
总结:这是一个有效的解决方案,可能对你很有用,但有两个注意事项你应该知道。
- 不适合同时进行多个API调用
在我们使用两个或更多的API调用来加载页面之前,这种方法需要一些改进。在这个场景中,我们希望持续显示进度条,直到所有API调用返回为止。此问题的常见解决方案是创建一个保存加载状态的加载Vuex模块。
- 在返回API调用之前首屏呈现一定的空白
在某些网页上,在数据完全之前看到该页的部分元素并不是很好的用户体验,最好是拿到数据后在进行渲染。我们来看看其他的方案
三、解决方案2:组件内的路由守卫beforeRouteEnter
同样的我们安装nprogress,并在main.js中引入css
不同的是我们这次在对应的页面组件中引入NProgress,而不是在请求中
实例如下:
1 //page.vue 2 import store from './store' 3 import NProgress from 'nprogress' 4 5 //组件渲染之前的生命周期函数 6 beforeRouteEnter(routeTo、routeFrom、next){ 7 NProgress.start()// 启动进度条 8 由于组件尚未创建,因此不能在此处使用this关键字。 9 store.dispatch('event/fetchEvent,routeTo.params.id).(data => { 10 console.log(data)// 获取数据 11 NProgress.done()// 当操作完成时,完成进度条 12 next()// 只有调用此命令,导航才会继续 13 }) 14 },
这样我们就能确保获取到组件渲染所需的数据后才渲染组件
四、解决方案3:路由全局守卫与单路由守卫Global and Per-Route Guards
同样的先安装引入NProgress
在route.js中引入NProgress
// route.js // 在每个路由行为之前 router.beforeach((routeTo, routeFrom, next) => { //启动路由进度条 NProgress.start() next() }) // 在每个路由行为之后 router.afterEach(() => { // 完成路由进度条
NProgress.done() })
这样我们已经初步完成NProgress的布置,但是我们还是需要在确保页面数据都请求到之后才执行router.afterEach,有两种方法:
- 在页面中使用beforeRouteEnter生命周期函数,但是这里推荐使用下一种方案
- 在路由列表中使用beforeEnter守卫,配合使用props,我们可以将vuex从页面组件中移除,这样我们的组件会变得更加的简洁,也更容易维护
1 Vue.use(Router) 2 3 const router = new Router({ 4 mode: 'history', 5 routes: [ 6 { 7 path: '/event/:id', 8 name: 'event-show', 9 component: EventShow, 10 props: true, 11 beforeEnter(routeTo, routeFrom, next) { 12 store.dispatch('event/fetchEvent', routeTo.params.id).then(event => { 13 routeTo.params.event = event 14 next() 15 }) 16 } 17 } 18 ] 19 }
单独的配置路由列表,无数据请求的路由页,进度条可以瞬间完成,配置beforeEnter的将等待数据请求成功后才渲染组件。
另外,这样通过组件传参的方式将数据传递到组件中,可以将vuex从组件中移除,优化了组件,使其更加具有维护性