從0到1使用VUE-CLI3開發實戰(五):模組化VUEX及使用vuetify

周小肆發表於2019-01-25

小肆前幾天發了一篇2019年Vue精品開源專案庫的彙總,今天小肆要使用的是在UI元件中排行第三的Vuetify。

vuetify介紹

Vuetify是一個漸進式的框架,完全根據Material Design規範開發,一共擁有80多個元件,對移動端支援非常好。

支援SSR(服務端渲染),SPA(單頁應用程式),PWA(漸進式Web應用程式)和標準HTML頁面。

vuetify官方文件給出了它具備的幾點優勢:

從0到1使用VUE-CLI3開發實戰(五):模組化VUEX及使用vuetify

安裝

安裝算是比較簡單了,在專案目錄輸入以下命令就OK:

vue add vuetify
複製程式碼

但這時有一個問題,如果我們使用預設的icon,index.html裡面引入的是google的連結

  <link href='https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons' rel="stylesheet">
複製程式碼

我們需要替換成國內的

https://fonts.cat.net/
複製程式碼

底部導航元件

今天我們先用vuetify的語法寫一個底部導航的元件,先放程式碼:

<template>
  <v-card flat>
    <v-bottom-nav :value="true" fixed color="transparent">
      <v-btn color="teal" :to="{path:'/'}" flat>
        <span>首頁</span>
        <v-icon>home</v-icon>
      </v-btn>

      <v-btn color="teal" :to="{path:'/lottery'}" flat>
        <span>足彩</span>
        <v-icon>favorite</v-icon>
      </v-btn>

      <v-btn color="teal" :to="{path:'/competition'}" flat>
        <span>賽事</span>
        <v-icon>place</v-icon>
      </v-btn>

      <v-btn color="teal" :to="{path:'/course'}" flat>
        <span>課程</span>
        <v-icon>music_video</v-icon>
      </v-btn>
    </v-bottom-nav>
  </v-card>
</template>
複製程式碼

這裡主要用到的是v-bottom-nav這個API,下面這張圖顯示了它可用的全部屬性:

從0到1使用VUE-CLI3開發實戰(五):模組化VUEX及使用vuetify

上述程式碼的實際顯示效果:

從0到1使用VUE-CLI3開發實戰(五):模組化VUEX及使用vuetify

模組化vuex

為了使用方便,我們改造一下vuex,新建store目錄,目錄結構如下:

從0到1使用VUE-CLI3開發實戰(五):模組化VUEX及使用vuetify

更改store.js

import Vue from 'vue'
import Vuex from 'vuex'
import app from './store/modules/app'
import user from './store/modules/user'
import getters from './store/getters'

Vue.use(Vuex)

const store = new Vuex.Store({
  modules: {
    app,
    user
  },
  getters
})

export default store
複製程式碼

全域性loading

昨天我們配置了axios,今天我們來配置一下全域性loading。

先寫一個元件RequestLoading.vue
<template>
  <transition name="fade-transform" mode="out-in">
    <div class="request-loading-component" v-if="requestLoading">
      <v-progress-circular :size="50" color="primary" indeterminate></v-progress-circular>
    </div>
  </transition>
</template>

<script>
import { mapGetters } from 'vuex'

export default {
  name: 'RequestLoading',
  computed: {
    ...mapGetters(['requestLoading'])
  }
}
</script>

<style lang="stylus" scoped>
.request-loading-component {
  position: fixed;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
  background-color: rgba(48, 65, 86, 0.5);
  font-size: 150px;
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
  z-index: 999999;
}
</style>
複製程式碼

這裡我們用到了,vuetify中的v-progress-circular

接下來我們配置一下vuex

app.js
const app = {
  state: {
    requestLoading: 0
  },
  mutations: {
    SET_LOADING: (state, status) => {
      // error 的時候直接重置
      if (status === 0) {
        state.requestLoading = 0
        return
      }
      if (status) {
        ++state.requestLoading
      } else {
        --state.requestLoading
      }
    }
  },
  actions: {
    SetLoading({ commit }, status) {
      commit('SET_LOADING', status)
    }
  }
}

export default app
複製程式碼
getter.js
const getters = {
  requestLoading: (state) => state.app.requestLoading,
  token: (state) => state.user.token,
  avatar: (state) => state.user.avatar,
  name: (state) => state.user.name
}

export default getters
複製程式碼
最後我們修改一下axios.js
// 新增請求攔截器
service.interceptors.request.use(
  (config) => {
    if (config.method === 'post' || config.method === 'put') {
      // post、put 提交時,將物件轉換為string, 為處理Java後臺解析問題
      config.data = JSON.stringify(config.data)
    }
    // loading + 1
    store.dispatch('SetLoading', true)
    // 請求傳送前進行處理
    return config
  },
  (error) => {
    // 請求錯誤處理
    // loading 清 0
    setTimeout(function() {
      store.dispatch('SetLoading', 0)
    }, 300)

    return Promise.reject(error)
  }
)

// 新增響應攔截器
service.interceptors.response.use(
  (response) => {
    let { data, headers } = response

    if (headers['x-auth-token']) {
      data.token = headers['x-auth-token']
    }
    // loading - 1
    store.dispatch('SetLoading', false)
    return data
  },
  (error) => {
    let info = {},
      { status, statusText, data } = error.response

    if (!error.response) {
      info = {
        code: 5000,
        msg: 'Network Error'
      }
    } else {
      // 此處整理錯誤資訊格式
      info = {
        code: status,
        data: data,
        msg: statusText
      }
    }
    // loading - 1
    store.dispatch('SetLoading', false)
    return Promise.reject(info)
  }
)
複製程式碼

這樣我們在等待介面返回資料是就會看到下面這樣子:

從0到1使用VUE-CLI3開發實戰(五):模組化VUEX及使用vuetify

小結

好啦 ,今天就到這裡吧,如果有什麼疑問,可以下面留言,小肆會及時回覆的。記得點好看呦!

前置閱讀:

  1. 用vue-cli3從0到1做一個完整功能手機站(一)
  2. 從0到1開發實戰手機站(二):Git提交規範配置
  3. 從0到1使用VUE-CLI3開發實戰(三): ES6知識儲備
  4. 從0到1使用VUE-CLI3開發實戰(四):Axios封裝
    從0到1使用VUE-CLI3開發實戰(五):模組化VUEX及使用vuetify

相關文章