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