在開始前,請先看過一遍Nuxt Loading官方文件
如果沒有要調整progress bar的位置,可直接在nuxt.config.js內設定loading的property就好
(2.x版官方提供的設定值如下圖)
本文主要說明Hamsterism所使用的客製化loading component如何實作
在切換頁面時,會發現在頂端黑色nav bar下方會快速地跑過progress bar動畫
為了讓progress bar固定在nav bar下方,我選擇採自製loading component的方式
直接上component程式碼
<template> <div v-if="status" :class="{ successful: success, failed: failure }" class="loading-bar" :style="barOpacity" > <div :class="{ failed: failure }" class="loading-bar-shadow" :style="barOpacity" ></div> </div> </template> <script> export default { data() { return { error: false, success: false, failure: false, } }, computed: { barOpacity() { return { opacity: this.status ? '1' : '0', } }, status() { return this.$store.getters['isLoading'] }, }, methods: { start() { this.$store.commit('unload') this.success = false this.failure = false this.$store.commit('load') }, finish() { this.success = true this.$store.dispatch('unload') }, fail(error) { this.error = error this.failure = true }, }, } </script> <style lang="scss" scoped> .loading-bar { display: block; position: fixed; top: 3rem; left: 0; right: 0; height: 5px; z-index: 49; transition: all 0.3s linear; background-color: $hamsterism-btn-color-primary; overflow: hidden; animation: loading 5s ease-in-out; animation-fill-mode: both; &.failed { background-color: $hamsterism-btn-color-danger-dark; width: 100%; animation: none; } &.successful { width: 100%; animation: none; } &-shadow { display: block; position: absolute; right: 0; width: 100px; height: 3px; box-shadow: 1px 0px 10px $hamsterism-btn-color-primary; transform: rotate(3deg) translate(0px, -1px); &.failed { box-shadow: 1px 0px 10px $hamsterism-btn-color-danger-dark; } } } @keyframes loading { 0% { width: 0; } 100% { width: 100%; } } </style>
關鍵method
官方提供四個客製化時會用到的method:start()、finish()、fail(error)、increase(num)
前三個開始、結束、失敗很直觀沒問題
最後一項increase(num)由於缺少範例,所以我不知道該怎用,直接放棄Ovo
因為放棄了控制一次increase多少進度的功能,所以整個載入以固定時長的動畫實作
動畫設計很簡單,從0%到100%,控制width變化
時長我設為5s,超過五秒以上的載入會卡在100%的意思
早於5s完成的話,Nuxt會觸發finish(),在scss的&.successful
控制使width變為100%
同理,若載入失敗,Nuxt會觸發fail(),在scss的&.failed
控制width變為100%且變色
Store管理loading狀態
看官網文件會發現,它的loading
變數寫在component的data
內
原先我也是用這寫法,但發現頁面切換上animation狀態變超怪...
由於搞不懂Nuxt呼叫loading component的變數記憶情況
我改將loading的狀態統一由store(vuex)來管理,最沒爭議Ovo
直接寫在~/store/index.js (你要另外創一個loading.js也可以)
export const state = () => ({ loading: false, }) export const getters = { isLoading(state) { return state.loading }, } export const mutations = { load(state) { state.loading = true }, unload(state) { state.loading = false }, } export const actions = { unload({ commit }) { setTimeout(() => { commit('unload') }, 300) }, }
更改狀態的mutation很簡單,需要注意的關鍵點在action unload()
以setTimeout延遲300ms才發出unload的狀態變更,來配合 transition: all 0.3s linear;
不然progress bar會提前消失唷!
至於固定特定位置、變更顏色、變更粗細等,都在scss的 .loading-bar 內客製
修改nuxt.config.js
最後一步,在nuxt.config.js告訴Nuxt你的loading要用自己做出來的組件
(component位置就看你放哪兒)
export default { //... loading: '~/components/ui/LoadingBar.vue', //... }
完成!👏👏👏