# [Vue] 使用NProgress輕鬆實現網頁載入進度條
###### tags: `Vue` `前端` `工作筆記`
## [實作目的]
有些頁面在跳轉上,或是送出請求的加載的比較慢,讓使用者知道目前的進度有極高的機會能增加使用者的耐心 (~~希望他不要一直按F5~~),以下是簡單的實作方式。
## [效果展示]
**載入中**
![](https://i.imgur.com/uAfHiZg.png)
## 安裝
直接於專案資料夾打開CMD下安裝指令:`npm install --save nprogress`
若要指定版本也可下參數,或是直接於`package.json`指定。
## NProgress使用方法
可以至該網址查看效果的差異:https://ricostacruz.com/nprogress/
```vue=
常用:
NProgress.start() // 進度條開始
NProgress.done() // 進度條結束(消失)
比較少用:
NProgress.set() // 將進度條設定在某百分比,範圍0~1.0
e.g. NProgress.set(0.5),進度條在一半的位置
NProgress.inc() // 進度條隨機少量的增加,但永遠不會到100%消失 (可以傳入參數當增量的特定值)
e.g. NProgress.inc(0.1),每次增加0.1直到最接近100%
NProgress.configure() // 進度條參數配置
```
## 程式碼
### 全域引入NProgress
通常會配置在全域的`main.ts`,記得css也要一起import。
configure可以設定多種配置,像是動畫速度、每次進度條增加多少...等。
```vue=
import NProgress from 'nprogress' // progress bar
import 'nprogress/nprogress.css' // progress bar style
NProgress.configure({ showSpinner: false })
```
這邊的`NProgress.configure({ showSpinner: false })`為關閉旋轉動畫。
開啟的樣子可參考:
https://segmentfault.com/img/bV7IrA?w=601&h=91
圖片來源:https://segmentfault.com/a/1190000014193675
### 修改NProgress的CSS樣式
NProgress內建的`nprogress.css`檔案內寫好了預設的樣式,但我們通常不會直接去改套件現有的東西。
可以在專案全域環境下的CSS檔案中(通常會被`main.ts`引入 例如:`global.scss`)去設定該CSS,記得要加入`!important`去蓋掉原本預設的樣式。
### 在VueRouter內使用NProcess (頁面跳轉)
懶人包:`NProgress.start()`用在`beforeEach`函數內,`Nprogress.done()`用在跳轉完畢後,或是直接寫在`afterEach`函數內
:::success
beforeEach函式有3個參數
```vue=
Vue.beforeEach(function(to,from,next){})
```
afterEach函式有2個參數
```vue=
Vue.afterEach(function(to,from){})
```
==to==:準備要進入的路由位置
==from==:目前的路由位置(即將離開)
==next==:調用該方法,進入下一個callback function
:::
【範例】:
第3行 直接開始NProcess的進度條
第5行~第8行 是判斷目前使用者在Vue的localStorage內有沒有登入時紀錄的JWT TOKEN。如果有,且準備要進入的路由是登入頁`/user/login`的話,則調用next轉導至首頁`/dashboard/workplace`,隨後結束NProcess的進度條。
第9~47行 是邏輯的其他情境,可以作為參考。
第49~51行 則是只要在頁面跳轉完成後,一律結束NProcess的進度條。
```vue=
const whiteList = ['login', 'register', 'registerResult'] // no redirect whitelist
router.beforeEach((to, from, next) => {
NProgress.start() // start progress bar
to.meta && (typeof to.meta.title !== 'undefined' && setDocumentTitle(`${to.meta.title} - ${domTitle}`))
if (Vue.ls.get(ACCESS_TOKEN)) {
if (to.path === '/user/login') {
next({ path: '/dashboard/workplace' })
NProgress.done()
} else {
if (store.getters.roles.length === 0) {
store
.dispatch('GetInfo')
.then(res => {
const roles = res.data && res.data.role
store.dispatch('GenerateRoutes', { roles }).then(() => {
router.addRoutes(store.getters.addRouters)
const redirect = decodeURIComponent(from.query.redirect || to.path)
if (to.path === redirect) {
// set the replace: true so the navigation will not leave a history record
next({ ...to, replace: true })
} else {
next({ path: redirect })
}
})
})
.catch(() => {
notification.error({
message: '錯誤',
description: '取得帳號資料失敗,請重試'
})
store.dispatch('Logout').then(() => {
next({ path: '/user/login', query: { redirect: to.fullPath } })
})
})
} else {
next()
}
}
} else {
if (whiteList.includes(to.name)) {
next()
} else {
next({ path: '/user/login', query: { redirect: to.fullPath } })
NProgress.done() // if current page is login will not trigger afterEach hook, so manually handle it
}
}
})
router.afterEach(() => {
NProgress.done() // finish progress bar
})
```
### 在axios內使用NProcess (發送請求)
如果想在每次axios發送請求時也出現進度條,則可以透過設定`axios.interceptor.ts`來加入此功能。
【範例】:
```vue=
// 請求攔截器
axios.interceptors.request.use(
NProgress.start()
})
// 回應攔截器
axios.interceptors.response.use(
NProgress.done()
)
```
# **The End**