---
# System prepended metadata

title: '[Vue] 使用NProgress輕鬆實現網頁載入進度條'
tags: [前端, 工作筆記, Vue]

---

# [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**






