美文网首页程序员技术放肆聊让前端飞
从0到1使用VUE-CLI3开发实战(五):模块化VUEX及使用

从0到1使用VUE-CLI3开发实战(五):模块化VUEX及使用

作者: 周小肆 | 来源:发表于2019-01-26 00:05 被阅读11次

    小肆前几天发了一篇2019年Vue精品开源项目库的汇总,今天小肆要使用的是在UI组件中排行第三的Vuetify。

    vuetify介绍

    Vuetify是一个渐进式的框架,完全根据Material Design规范开发,一共拥有80多个组件,对移动端支持非常好。

    支持SSR(服务端渲染),SPA(单页应用程序),PWA(渐进式Web应用程序)和标准HTML页面。

    vuetify官方文档给出了它具备的几点优势:

    image

    安装

    安装算是比较简单了,在项目目录输入以下命令就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,下面这张图显示了它可用的全部属性:

    image

    上述代码的实际显示效果:


    image

    模块化vuex

    为了使用方便,我们改造一下vuex,新建store目录,目录结构如下:


    image

    更改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)
      }
    )
    

    这样我们在等待接口返回数据是就会看到下面这样子:


    image

    小结

    好啦 ,今天就到这里吧,如果有什么疑问,可以下面留言,小肆会及时回复的。记得点好看呦!

    前置阅读:

    1. 用vue-cli3从0到1做一个完整功能手机站(一)
    2. 从0到1开发实战手机站(二):Git提交规范配置
    3. 从0到1使用VUE-CLI3开发实战(三): ES6知识储备
    4. 从0到1使用VUE-CLI3开发实战(四):Axios封装
      image

    相关文章

      网友评论

        本文标题:从0到1使用VUE-CLI3开发实战(五):模块化VUEX及使用

        本文链接:https://www.haomeiwen.com/subject/trsbjqtx.html